예제 #1
0
static int32_t oscam_ser_send(struct s_client *client, const uchar * const buf, int32_t l)
{
  int32_t n;
  struct s_serial_client *serialdata=client->serialdata ;
  if (!client->pfd) return(0);
  cs_ftime(&serialdata->tps);
  serialdata->tpe=client->serialdata->tps;
  serialdata->tpe.millitm+=serialdata->oscam_ser_timeout+(l*(serialdata->oscam_ser_delay+1));
  serialdata->tpe.time+=(serialdata->tpe.millitm/1000);
  serialdata->tpe.millitm%=1000;
  n=oscam_ser_write(client, buf, l);
  cs_ftime(&serialdata->tpe);
  cs_ddump_mask(D_CLIENT, buf, l, "send %d of %d bytes to %s in %ld msec", n, l, remote_txt(),
                    1000*(serialdata->tpe.time-serialdata->tps.time)+serialdata->tpe.millitm-serialdata->tps.millitm);
  if (n!=l)
    cs_log("transmit error. send %d of %d bytes only !", n, l);
  return(n);
}
예제 #2
0
static int32_t radegast_recv(struct s_client *client, uchar *buf, int32_t l)
{
  int32_t n;
  if (!client->pfd) return(-1);
  if (client->typ == 'c') {  // server code
    if ((n=recv(client->pfd, buf, l, 0))>0)
      client->last=time((time_t *) 0);
  } else {  // client code
    if ((n=recv(client->pfd, buf, l, 0))>0) {
      cs_ddump_mask(D_CLIENT, buf, n, "radegast: received %d bytes from %s", n, remote_txt());
      client->last = time((time_t *) 0);
      if ((buf[0] == 0x02)&&(buf[1] == 0x12) && (buf[2] == 0x05)&&(buf[3] == 0x10)) return(n);  // dcw received
      else if ((buf[0] == 0x02)&&(buf[1] == 0x02) && (buf[2] == 0x04)&&(buf[3] == 0x00)) return(n);  // dcw no found
      else if ((buf[0] == 0x81)&&(buf[1] == 0x00)) return(n);  // cmd unknown
      else n = -1;// no cmd radegast disconnect
    }
  }
  return(n);
}
예제 #3
0
static int32_t radegast_recv(struct s_client *client, uchar *buf, int32_t l)
{
  int32_t n;
  if (!client->pfd) return(-1);
  if (client->typ == 'c') {  // server code
    if ((n=recv(client->pfd, buf, l, 0))>0)
      client->last=time((time_t *) 0);
  } else {  // client code
    if ((n=recv(client->pfd, buf, l, 0))>0) {
      cs_ddump_mask(D_CLIENT, buf, n, "radegast: received %d bytes from %s", n, remote_txt());
      client->last = time((time_t *) 0);

      if (buf[0] == 2) {  // dcw received
        if (buf[3] != 0x10) {  // dcw ok
          cs_log("radegast: no dcw");
          n = -1;
        }
      }
    }
  }
  return(n);
}
예제 #4
0
static int32_t ghttp_recv_int(struct s_client *client, uchar *buf, int32_t l)
{
	int32_t n = -1;
	s_ghttp *context = (s_ghttp *)client->ghttp;

	if(!client->pfd)
	{
		ll_clear(context->ecm_q);
		return -1;
	}

	if(client->reader->ghttp_use_ssl)
	{
#ifdef WITH_SSL
		n = SSL_read(context->ssl_handle, buf, l);
#endif
	}
	else { n = recv(client->pfd, buf, l, 0); }

	if(n > 0)
	{
		cs_debug_mask(D_CLIENT, "%s: received %d bytes from %s", client->reader->label, n, remote_txt());
		client->last = time((time_t *)0);

		if(n > 400)
		{
			buf[n] = '\0';
			cs_debug_mask(D_CLIENT, "%s: unexpected reply size %d - %s", client->reader->label, n, buf);
			return -1; // assumes google error, disconnects
		}
	}
	if(n < 5)
	{
		cs_debug_mask(D_CLIENT, "%s: read %d bytes, disconnecting", client->reader->label, n);
		n = -1;
	}
	return n;
}
예제 #5
0
static int32_t oscam_ser_recv(struct s_client *client, uchar *xbuf, int32_t l)
{
  int32_t s, p, n, r;
  uchar job=IS_BAD;
  static uchar lb;
  static int32_t have_lb=0;
  uchar *buf=xbuf+1;
  struct s_serial_client *serialdata=client->serialdata;

  if (!client->pfd) return(-1);
  cs_ftime(&serialdata->tps);
  serialdata->tpe=serialdata->tps;
  serialdata->tpe.millitm+=serialdata->oscam_ser_timeout;
  serialdata->tpe.time+=(serialdata->tpe.millitm/1000);
  serialdata->tpe.millitm%=1000;
  buf[0]=lb;
  for (s=p=r=0, n=have_lb; (s<4) && (p>=0); s++)
  {
    switch(s)
    {
      case 0:		// STAGE 0: skip known garbage from DSR9500
        if (oscam_ser_selrec(buf, 2-n, l, &n))
        {
          if ((buf[0]==0x0A) && (buf[1]==0x0D))
            p=(-4);
          if ((buf[0]==0x0D) && (buf[1]==0x0A))
            p=(-4);
        }
        else
          p=(-3);
        have_lb=0;
        break;
      case 1:		// STAGE 1: identify protocol
        p=(-3);
        if (oscam_ser_selrec(buf, 1, l, &n)) // now we have 3 bytes in buf
        {
	    if((buf[0] == 0x04) && (buf[1] == 0x00) && (buf[2] == 0x02)) {	//skip unsupported Advanced Serial Sharing Protocol HF 8900
		    oscam_ser_selrec(buf, 2, l, &n); // get rest 2 bytes to buffor
	        p=(-4);
		have_lb=0;
		break;
	    }
	    else {

            p=(-2);
        	if (client->typ == 'c')		 // HERE IS SERVER
        	{
        	    job=IS_ECM;		// assume ECM
        	    switch(buf[0])
        	    {
            		case 0x00: if( (buf[1]==0x01)&&(buf[2]==0x00) )
                    		   { p=P_GS; job=IS_LGO; serialdata->tpe.time++; } break;
            		case 0x01: if( (buf[1]&0xf0)==0xb0 ) p=P_GBOX;
                    		     else  {p=P_SSSP; job=IS_PMT;}
                        	break;	// pmt-request
            		case 0x02: p=P_HSIC; break;
            		case 0x03: switch(serialdata->oscam_ser_proto)
                    	     {
                        	case P_SSSP  :
                        	case P_GS    :
                        	case P_DSR95 : p=serialdata->oscam_ser_proto; break;
                        	case P_AUTO  : p=(buf[1]<0x30) ? P_SSSP : P_DSR95;
                                          break;	// auto for GS is useless !!
                            } break;
            		case 0x04: p=P_DSR95; job=IS_ECHO; serialdata->dsr9500type=P_DSR_GNUSMAS; break;
            		case 0x7E: p=P_ALPHA; if (buf[1]!=0x80) job=IS_BAD; break;
            		case 0x80:
            		case 0x81: p=P_BOMBA; break;
        	    }
        	}

        	else				// HERE IS CLIENT
        	{
        	    job=IS_DCW;		// assume DCW
        	    switch(serialdata->oscam_ser_proto)
        	    {
            		case P_HSIC : if ((buf[0]==4) && (buf[1]==4)) p=P_HSIC; break;
            		case P_BOMBA: p=P_BOMBA; break;
            		case P_DSR95: if (buf[0]==4) p=P_DSR95; break;
            		case P_ALPHA: if (buf[0]==0x88) p=P_ALPHA; break;
        	    }
        	}
            if ((serialdata->oscam_ser_proto!=p) && (serialdata->oscam_ser_proto!=P_AUTO))
        	p=(-2);
    	    }
        }
        break;
      case 2:		// STAGE 2: examine length
        if (client->typ == 'c') switch(p)
        {
          case P_SSSP  : r=(buf[1]<<8)|buf[2]; break;
          case P_BOMBA : r=buf[2]; break;
          case P_HSIC  : if (oscam_ser_selrec(buf, 12, l, &n)) r=buf[14];
                         else p=(-1);
                         break;
          case P_DSR95 : if( job==IS_ECHO )
                         {
                           r=17*serialdata->samsung_dcw-3+serialdata->samsung_0a;
                           serialdata->samsung_dcw=serialdata->samsung_0a=0;
                         }
                         else
                         {
                           if (oscam_ser_selrec(buf, 16, l, &n))
                           {
                             uchar b;
                             if (cs_atob(&b, (char *)buf+17, 1)<0)
                               p=(-2);
                             else {
                               r=(b<<1);
                               r+=(serialdata->dsr9500type==P_DSR_WITHSID)?4:0;
                             }
                           }
                           else p=(-1);
                         }
                         break;
          case P_GS    : if (job==IS_LGO)
                           r=5;
                         else
                         {
                           if (oscam_ser_selrec(buf, 1, l, &n))
                             r=(buf[3]<<8)|buf[2];
                           else p=(-1);
                         }
                         break;
          case P_ALPHA : r=-0x7F;	// char specifying EOT
                         break;
          case P_GBOX  : r=((buf[1]&0xf)<<8) | buf[2];
                         serialdata->gbox_lens.cat_len = r;
                         break;
          default      : serialdata->dsr9500type=P_DSR_AUTO;
        }
        else switch(p)
        {
          case P_HSIC   : r=(buf[2]==0x3A) ? 20 : 0; break; // 3A=DCW / FC=ECM was wrong
          case P_BOMBA  : r=13; break;
          case P_DSR95  : r=14; break;
          case P_ALPHA  : r=(buf[1]<<8)|buf[2]; break;	// should be 16 always
        }
        break;
      case 3:		// STAGE 3: get the rest ...
        if (r>0)	// read r additional bytes
        {
          int32_t all = n+r;
          if( !oscam_ser_selrec(buf, r, l, &n) )
          {
            cs_debug_mask(D_CLIENT, "not all data received, waiting another 50 ms");
            serialdata->tpe.millitm+=50;
            if( !oscam_ser_selrec(buf, all-n, l, &n) )
              p=(-1);
          }
          // auto detect DSR9500 protocol
          if( client->typ == 'c' && p==P_DSR95 && serialdata->dsr9500type==P_DSR_AUTO )
          {
            serialdata->tpe.millitm+=20;
            if( oscam_ser_selrec(buf, 2, l, &n) )
            {
              if( cs_atoi((char *)buf+n-2, 1, 1)==0xFFFFFFFF )
              {
                switch( (buf[n-2]<<8)|buf[n-1] )
                {
                  case 0x0A0D : serialdata->dsr9500type=P_DSR_OPEN; break;
                  case 0x0D0A : serialdata->dsr9500type=P_DSR_PIONEER; break;
                  default     : serialdata->dsr9500type=P_DSR_UNKNOWN; break;
                }
              }else{
                if( oscam_ser_selrec(buf, 2, l, &n) )
                  if( cs_atoi((char *)buf+n-2, 1, 1)==0xFFFFFFFF )
                    serialdata->dsr9500type=P_DSR_UNKNOWN;
                  else
                    serialdata->dsr9500type=P_DSR_WITHSID;
                else {
                  serialdata->dsr9500type=P_DSR_UNKNOWN;
                  p=(-1);
                }
              }
            }
            else
              serialdata->dsr9500type=P_DSR_GNUSMAS;
            if( p )
              cs_log("detected dsr9500-%s type receiver",
                      dsrproto_txt[serialdata->dsr9500type]);
          }
          // gbox
          if( client->typ == 'c' && p==P_GBOX )
          {
            int32_t j;
            for( j=0; (j<3) && (p>0); j++)
              switch( j )
              {
                case 0: // PMT head
                  if( !oscam_ser_selrec(buf, 3, l, &n) )
                    p=(-1);
                  else if( !(buf[n-3]==0x02 && (buf[n-2]&0xf0)==0xb0) )
                    p=(-2);
                  break;
                case 1: // PMT + ECM header
                  serialdata->gbox_lens.pmt_len=((buf[n-2]&0xf)<<8)|buf[n-1];
                  if( !oscam_ser_selrec(buf, serialdata->gbox_lens.pmt_len+3, l, &n) )
                    p=(-1);
                  break;
                case 2: // ECM + ECM PID
                  serialdata->gbox_lens.ecm_len=((buf[n-2]&0xf)<<8)|buf[n-1];
                  if( !oscam_ser_selrec(buf, serialdata->gbox_lens.ecm_len+4, l, &n) )
                    p=(-1);
              }
          } // gbox
        }
        else if (r<0)	// read until specified char (-r)
        {
          while((buf[n-1]!=(-r)) && (p>0))
            if (!oscam_ser_selrec(buf, 1, l, &n))
              p=(-1);
        }
        break;
    }
  }
  if (p==(-2) || p==(-1)) {
    oscam_ser_selrec(buf, l-n, l, &n);	// flush buffer
    serialdata->serial_errors++;
  }
  cs_ftime(&serialdata->tpe);
  cs_ddump_mask(D_CLIENT, buf, n, "received %d bytes from %s in %ld msec", n, remote_txt(),
                    1000*(serialdata->tpe.time-serialdata->tps.time)+serialdata->tpe.millitm-serialdata->tps.millitm);
  client->last=serialdata->tpe.time;
  switch(p)
  {
    case (-1): if (client->typ == 'c'&&(n>2)&&(buf[0]==2)&&(buf[1]==2)&&(buf[2]==2))
               {
                 oscam_ser_disconnect();
                 cs_log("humax powered on");	// this is nice ;)
               }
               else {
            	    if(client->typ == 'c' && buf[0] == 0x1 && buf[1] == 0x08 && buf[2] == 0x20 && buf[3] == 0x08) {
            		oscam_ser_disconnect();
                	cs_log("ferguson powered on");	// this is nice to ;)
    		    }
    		    else
                	cs_log(incomplete, n);
		}
               break;
    case (-2): cs_debug_mask(D_CLIENT, "unknown request or garbage");
               break;
  }
  xbuf[0]=(uchar) ((job<<4) | p);
  return((p<0)?0:n+1);
}
예제 #6
0
static int32_t ghttp_recv(struct s_client *client, uchar *buf, int32_t l)
{
  int32_t n = -1;
  if(!client->pfd) return (-1);

  if((n = recv(client->pfd, buf, l, 0)) > 0) {
    cs_debug_mask(D_CLIENT, "%s: received %d bytes from %s", client->reader->label, n, remote_txt());
    client->last = time((time_t *)0);

    if(n > 300) return -1; //assumes google error, disconnects
  }
  return n;
}
예제 #7
0
static int32_t camd35_recv(struct s_client *client, uchar *buf, int32_t l)
{
	int32_t rc, s, rs, n = 0, buflen = 0, len = 0;
	for(rc = rs = s = 0; !rc; s++)
	{
		switch(s)
		{
		case 0:
			if(!client->udp_fd) { return (-9); }
			if(client->is_udp && client->typ == 'c')
			{
				rs = recv_from_udpipe(buf);
			}
			else
			{
				//read minimum packet size (4 byte ucrc + 32 byte data) to detect packet size (tcp only)

				//rs = cs_recv(client->udp_fd, buf, client->is_udp ? l : 36, 0);
				if(client->is_udp){
					while (1){
					rs = cs_recv(client->udp_fd, buf, l, 0);
						if (rs < 0){
							if(errno == EINTR) { continue; }  // try again in case of interrupt
							if(errno == EAGAIN) { continue; }  //EAGAIN needs select procedure again
							cs_log_dbg(client->typ == 'c' ? D_CLIENT : D_READER, "ERROR: %s (errno=%d %s)", __func__, errno, strerror(errno));
							break;
						}else {break;}
					}
				}else{
					int32_t tot=36, readed=0;
					rs = 0;
					do
					{
						readed = cs_recv(client->udp_fd, buf+rs, tot, 0);
						if (readed < 0){
							if(errno == EINTR) { continue; }  // try again in case of interrupt
							if(errno == EAGAIN) { continue; }  //EAGAIN needs select procedure again
							cs_log_dbg(client->typ == 'c' ? D_CLIENT : D_READER, "ERROR: %s (errno=%d %s)", __func__, errno, strerror(errno));
							break;
						}
						if (readed == 0){ // nothing to read left!
							rc = -5;
							break;
						}
						if (readed > 0){ // received something, add it!
							tot-=readed;
						rs+=readed;
						}
					}
					while(tot!=0);
				}

			}
			if(rs < 36)
			{	
				if(rc != -5)
					{ rc = -1; }
				goto out;
			}
			break;
		case 1:
			switch(camd35_auth_client(client, buf))
			{
			case  0:
				break;  // ok
			case  1:
				rc = -2;
				break; // unknown user
			default:
				rc = -9;
				break; // error's from cs_auth()
			}
			memmove(buf, buf + 4, rs -= 4);
			break;
		case 2:
			aes_decrypt(client->aes_keys, buf, rs);
			if(rs != boundary(4, rs))
				cs_log_dbg(client->typ == 'c' ? D_CLIENT : D_READER,
							  "WARNING: packet size has wrong decryption boundary");

			n = (buf[0] == 3) ? 0x34 : 0;

			//Fix for ECM request size > 255 (use ecm length field)
			if(buf[0] == 0)
				{ buflen = (((buf[21] & 0x0f) << 8) | buf[22]) + 3; }
			else if(buf[0] == 0x3d || buf[0] == 0x3e || buf[0] == 0x3f)  //cacheex-push
				{ buflen = buf[1] | (buf[2] << 8); }
			else
				{ buflen = buf[1]; }

			n = boundary(4, n + 20 + buflen);
			if(!(client->is_udp && client->typ == 'c') && (rs < n) && ((n - 32) > 0))
			{

				//len = cs_recv(client->udp_fd, buf+32, n-32, 0); // read the rest of the packet
				int32_t tot=n-32, readed=0;
				len = 0;
				do{
					readed = cs_recv(client->udp_fd, buf+32+len, tot, 0); // read the rest of the packet
					if (readed < 0){
						if(errno == EINTR) { continue; }  // try again in case of interrupt
						if(errno == EAGAIN) { continue; }  //EAGAIN needs select procedure again
						cs_log_dbg(client->typ == 'c' ? D_CLIENT : D_READER, "ERROR: %s (errno=%d %s)", __func__, errno, strerror(errno));
						break;
					}
					if (readed == 0){ // nothing to read left!
						break;
					}
					if (readed > 0){ // received something, add it!
					tot-=readed;
					len+=readed;
					}
				}
				while(tot!=0);


				if(len > 0)
				{
					rs += len;
					aes_decrypt(client->aes_keys, buf + 32, len);
				}
				if(len < 0)
				{
					rc = -1;
					goto out;
				}
			}

			cs_log_dump_dbg(client->typ == 'c' ? D_CLIENT : D_READER,
						  buf, rs, "received %d bytes from %s", rs, remote_txt());

			if(n < rs)
				cs_log_dbg(client->typ == 'c' ? D_CLIENT : D_READER,
							  "ignoring %d bytes of garbage", rs - n);
			else if(n > rs) { rc = -3; }
			break;
		case 3:
			if(crc32(0L, buf + 20, buflen) != b2i(4, buf + 4)) { rc = -4; }
			if(!rc) { rc = n; }
			break;
		}
	}

out:
	if((rs > 0) && ((rc == -1) || (rc == -2)))
	{
		cs_log_dump_dbg(client->typ == 'c' ? D_CLIENT : D_READER, buf, rs,
					  "received %d bytes from %s (native)", rs, remote_txt());
	}
	if(rc >= 0) { client->last = time(NULL); }  // last client action is now
	switch(rc)
	{
		//case 0:   break;
	case -1:
		cs_log("packet is too small (received %d bytes, expected %d bytes)", rs, l);
		break;
	case -2:
		if(cs_auth_client(client, 0, "unknown user"))
			{ cs_disconnect_client(client); }
		break;
	case -3:
		cs_log("incomplete request !");
		break;
	case -4:
		cs_log("checksum error (wrong password ?)");
		break;
	case -5:
		cs_log_dbg(client->typ == 'c' ? D_CLIENT : D_READER, "connection closed");
		break;		
		//default:  cs_log_dbg(D_TRACE, "camd35_recv returns rc=%d", rc); break;
	}

	return (rc);
}