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); }
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); }
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); }
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; }
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); }
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; }
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); }