void handle_packet(apacket *p, atransport *t) { asocket *s; D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0], ((char*) (&(p->msg.command)))[1], ((char*) (&(p->msg.command)))[2], ((char*) (&(p->msg.command)))[3]); print_packet("recv", p); switch(p->msg.command){ case A_SYNC: if(p->msg.arg0){ send_packet(p, t); if(HOST) send_connect(t); } else { t->connection_state = CS_OFFLINE; handle_offline(t); send_packet(p, t); } return; case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */ /* XXX verify version, etc */ if(t->connection_state != CS_OFFLINE) { t->connection_state = CS_OFFLINE; handle_offline(t); } parse_banner((char*) p->data, t); handle_online(); if(!HOST) send_connect(t); break; case A_OPEN: /* OPEN(local-id, 0, "destination") */ if(t->connection_state != CS_OFFLINE) { char *name = (char*) p->data; name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0; s = create_local_service_socket(name); if(s == 0) { send_close(0, p->msg.arg0, t); } else { s->peer = create_remote_socket(p->msg.arg0, t); s->peer->peer = s; send_ready(s->id, s->peer->id, t); s->ready(s); } } break; case A_OKAY: /* READY(local-id, remote-id, "") */ if(t->connection_state != CS_OFFLINE) { if((s = find_local_socket(p->msg.arg1))) { if(s->peer == 0) { s->peer = create_remote_socket(p->msg.arg0, t); s->peer->peer = s; } s->ready(s); } } break; case A_CLSE: /* CLOSE(local-id, remote-id, "") */ if(t->connection_state != CS_OFFLINE) { if((s = find_local_socket(p->msg.arg1))) { s->close(s); } } break; case A_WRTE: if(t->connection_state != CS_OFFLINE) { if((s = find_local_socket(p->msg.arg1))) { unsigned rid = p->msg.arg0; p->len = p->msg.data_length; if(s->enqueue(s, p) == 0) { D("Enqueue the socket\n"); send_ready(s->id, rid, t); } return; } } break; default: printf("handle_packet: what is %08x?!\n", p->msg.command); } put_apacket(p); }
void handle_packet(apacket *p, atransport *t) { asocket *s; D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0], ((char*) (&(p->msg.command)))[1], ((char*) (&(p->msg.command)))[2], ((char*) (&(p->msg.command)))[3]); print_packet("recv", p); switch(p->msg.command){ case A_SYNC: if(p->msg.arg0){ send_packet(p, t); if(HOST) send_connect(t); } else { t->connection_state = CS_OFFLINE; handle_offline(t); send_packet(p, t); } return; case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */ /* XXX verify version, etc */ if(t->connection_state != CS_OFFLINE) { t->connection_state = CS_OFFLINE; handle_offline(t); } parse_banner((char*) p->data, t); if (HOST || !auth_enabled) { handle_online(t); if(!HOST) send_connect(t); } else { #ifndef NO_AUTH send_auth_request(t); #endif } break; #ifndef NO_AUTH case A_AUTH: if (p->msg.arg0 == ADB_AUTH_TOKEN) { t->key = adb_auth_nextkey(t->key); if (t->key) { send_auth_response(p->data, p->msg.data_length, t); } else { /* No more private keys to try, send the public key */ send_auth_publickey(t); } } else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) { if (adb_auth_verify(t->token, p->data, p->msg.data_length)) { adb_auth_verified(t); t->failed_auth_attempts = 0; } else { if (t->failed_auth_attempts++ > 10) adb_sleep_ms(1000); send_auth_request(t); } } else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) { adb_auth_confirm_key(p->data, p->msg.data_length, t); } break; #endif case A_OPEN: /* OPEN(local-id, 0, "destination") */ if (t->online) { char *name = (char*) p->data; name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0; s = create_local_service_socket(name); if(s == 0) { send_close(0, p->msg.arg0, t); } else { s->peer = create_remote_socket(p->msg.arg0, t); s->peer->peer = s; send_ready(s->id, s->peer->id, t); s->ready(s); } } break; case A_OKAY: /* READY(local-id, remote-id, "") */ if (t->online) { if((s = find_local_socket(p->msg.arg1))) { if(s->peer == 0) { s->peer = create_remote_socket(p->msg.arg0, t); s->peer->peer = s; } s->ready(s); } } break; case A_CLSE: /* CLOSE(local-id, remote-id, "") */ if (t->online) { D("CLOSE(%d, %d, \"\")\n", p->msg.arg0, p->msg.arg1); if((s = find_local_socket(p->msg.arg1))) { s->close(s); } } break; case A_WRTE: if (t->online) { if((s = find_local_socket(p->msg.arg1))) { unsigned rid = p->msg.arg0; p->len = p->msg.data_length; if(s->enqueue(s, p) == 0) { D("Enqueue the socket\n"); send_ready(s->id, rid, t); } return; } } break; default: printf("handle_packet: what is %08x?!\n", p->msg.command); } put_apacket(p); }
void handle_packet(apacket *p, atransport *t) { asocket *s; D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0], ((char*) (&(p->msg.command)))[1], ((char*) (&(p->msg.command)))[2], ((char*) (&(p->msg.command)))[3]); print_packet("recv", p); switch(p->msg.command){ case A_SYNC: if(p->msg.arg0){ send_packet(p, t); if(HOST) send_connect(t); } else { t->connection_state = CS_OFFLINE; handle_offline(t); send_packet(p, t); } return; case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */ /* XXX verify version, etc */ if(t->connection_state != CS_OFFLINE) { t->connection_state = CS_OFFLINE; handle_offline(t); } parse_banner(reinterpret_cast<const char*>(p->data), t); if (HOST || !auth_required) { handle_online(t); if (!HOST) send_connect(t); } else { send_auth_request(t); } break; case A_AUTH: if (p->msg.arg0 == ADB_AUTH_TOKEN) { t->connection_state = CS_UNAUTHORIZED; t->key = adb_auth_nextkey(t->key); if (t->key) { send_auth_response(p->data, p->msg.data_length, t); } else { /* No more private keys to try, send the public key */ send_auth_publickey(t); } } else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) { if (adb_auth_verify(t->token, p->data, p->msg.data_length)) { adb_auth_verified(t); t->failed_auth_attempts = 0; } else { if (t->failed_auth_attempts++ > 10) adb_sleep_ms(1000); send_auth_request(t); } } else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) { adb_auth_confirm_key(p->data, p->msg.data_length, t); } break; case A_OPEN: /* OPEN(local-id, 0, "destination") */ if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) { char *name = (char*) p->data; name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0; s = create_local_service_socket(name); if(s == 0) { send_close(0, p->msg.arg0, t); } else { s->peer = create_remote_socket(p->msg.arg0, t); s->peer->peer = s; send_ready(s->id, s->peer->id, t); s->ready(s); } } break; case A_OKAY: /* READY(local-id, remote-id, "") */ if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) { if((s = find_local_socket(p->msg.arg1, 0))) { if(s->peer == 0) { /* On first READY message, create the connection. */ s->peer = create_remote_socket(p->msg.arg0, t); s->peer->peer = s; s->ready(s); } else if (s->peer->id == p->msg.arg0) { /* Other READY messages must use the same local-id */ s->ready(s); } else { D("Invalid A_OKAY(%d,%d), expected A_OKAY(%d,%d) on transport %s\n", p->msg.arg0, p->msg.arg1, s->peer->id, p->msg.arg1, t->serial); } } } break; case A_CLSE: /* CLOSE(local-id, remote-id, "") or CLOSE(0, remote-id, "") */ if (t->online && p->msg.arg1 != 0) { if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) { /* According to protocol.txt, p->msg.arg0 might be 0 to indicate * a failed OPEN only. However, due to a bug in previous ADB * versions, CLOSE(0, remote-id, "") was also used for normal * CLOSE() operations. * * This is bad because it means a compromised adbd could * send packets to close connections between the host and * other devices. To avoid this, only allow this if the local * socket has a peer on the same transport. */ if (p->msg.arg0 == 0 && s->peer && s->peer->transport != t) { D("Invalid A_CLSE(0, %u) from transport %s, expected transport %s\n", p->msg.arg1, t->serial, s->peer->transport->serial); } else { s->close(s); } } } break; case A_WRTE: /* WRITE(local-id, remote-id, <data>) */ if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) { if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) { unsigned rid = p->msg.arg0; p->len = p->msg.data_length; if(s->enqueue(s, p) == 0) { D("Enqueue the socket\n"); send_ready(s->id, rid, t); } return; } } break; default: printf("handle_packet: what is %08x?!\n", p->msg.command); } put_apacket(p); }
void handle_packet(apacket *p, atransport *t) { D("handle_packet() %c%c%c%c", ((char*) (&(p->msg.command)))[0], ((char*) (&(p->msg.command)))[1], ((char*) (&(p->msg.command)))[2], ((char*) (&(p->msg.command)))[3]); print_packet("recv", p); switch(p->msg.command){ case A_SYNC: if (p->msg.arg0){ send_packet(p, t); #if ADB_HOST send_connect(t); #endif } else { t->connection_state = kCsOffline; handle_offline(t); send_packet(p, t); } return; case A_CNXN: // CONNECT(version, maxdata, "system-id-string") handle_new_connection(t, p); break; case A_AUTH: if (p->msg.arg0 == ADB_AUTH_TOKEN) { t->connection_state = kCsUnauthorized; send_auth_response(p->data, p->msg.data_length, t); } else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) { if (adb_auth_verify(t->token, sizeof(t->token), p->data, p->msg.data_length)) { adb_auth_verified(t); t->failed_auth_attempts = 0; } else { if (t->failed_auth_attempts++ > 256) adb_sleep_ms(1000); send_auth_request(t); } } else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) { adb_auth_confirm_key(p->data, p->msg.data_length, t); } break; case A_OPEN: /* OPEN(local-id, 0, "destination") */ if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) { char *name = (char*) p->data; name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0; asocket* s = create_local_service_socket(name, t); if (s == nullptr) { send_close(0, p->msg.arg0, t); } else { s->peer = create_remote_socket(p->msg.arg0, t); s->peer->peer = s; send_ready(s->id, s->peer->id, t); s->ready(s); } } break; case A_OKAY: /* READY(local-id, remote-id, "") */ if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) { asocket* s = find_local_socket(p->msg.arg1, 0); if (s) { if(s->peer == 0) { /* On first READY message, create the connection. */ s->peer = create_remote_socket(p->msg.arg0, t); s->peer->peer = s; s->ready(s); } else if (s->peer->id == p->msg.arg0) { /* Other READY messages must use the same local-id */ s->ready(s); } else { D("Invalid A_OKAY(%d,%d), expected A_OKAY(%d,%d) on transport %s", p->msg.arg0, p->msg.arg1, s->peer->id, p->msg.arg1, t->serial); } } else { // When receiving A_OKAY from device for A_OPEN request, the host server may // have closed the local socket because of client disconnection. Then we need // to send A_CLSE back to device to close the service on device. send_close(p->msg.arg1, p->msg.arg0, t); } } break; case A_CLSE: /* CLOSE(local-id, remote-id, "") or CLOSE(0, remote-id, "") */ if (t->online && p->msg.arg1 != 0) { asocket* s = find_local_socket(p->msg.arg1, p->msg.arg0); if (s) { /* According to protocol.txt, p->msg.arg0 might be 0 to indicate * a failed OPEN only. However, due to a bug in previous ADB * versions, CLOSE(0, remote-id, "") was also used for normal * CLOSE() operations. * * This is bad because it means a compromised adbd could * send packets to close connections between the host and * other devices. To avoid this, only allow this if the local * socket has a peer on the same transport. */ if (p->msg.arg0 == 0 && s->peer && s->peer->transport != t) { D("Invalid A_CLSE(0, %u) from transport %s, expected transport %s", p->msg.arg1, t->serial, s->peer->transport->serial); } else { s->close(s); } } } break; case A_WRTE: /* WRITE(local-id, remote-id, <data>) */ if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) { asocket* s = find_local_socket(p->msg.arg1, p->msg.arg0); if (s) { unsigned rid = p->msg.arg0; p->len = p->msg.data_length; if (s->enqueue(s, p) == 0) { D("Enqueue the socket"); send_ready(s->id, rid, t); } return; } } break; default: printf("handle_packet: what is %08x?!\n", p->msg.command); } put_apacket(p); }
void adb_auth_verified(atransport *t) { handle_online(t); send_connect(t); }
void connect_do(void *pri_work, const ip_report_t *r) { char shost_s[32]; union { void *ptr; send_pri_workunit_t *w; uint8_t *inc; } w_u; union { void *ptr; connection_status_t *c; } c_u; union { const uint8_t *packet; const ip_report_t *r; const uint16_t *len; } r_u; struct in_addr ia; uint64_t state_key=0; size_t dlen=0, pk_len=0; uint32_t dhost=0, shost=0; uint16_t sport=0, dport=0; if (r == NULL) { PANIC("r ptr NULL"); } if (state_tbl == NULL) { PANIC("state table null"); } if (pri_work == NULL) { PANIC("pri_work NULL"); } if (r->magic != IP_REPORT_MAGIC) { ERR("wrong magic number for IP report"); return; } state_key=get_connectionkey(r); dhost=r->host_addr; dport=r->sport; sport=r->dport; shost=r->send_addr; if (rbfind(state_tbl, state_key, &c_u.ptr) > 0) { DBG(M_CON, "connection with flags are %s status is %d", strtcpflgs(r->type), c_u.c->status); r_u.r=r; if (r_u.r->doff) { pk_len=r_u.r->doff; r_u.packet += sizeof(ip_report_t); if (*r_u.len != pk_len) { ERR("report is damaged?, packet seems broken"); return; } else { r_u.len++; dlen=try_and_extract_tcp_data(r_u.packet, pk_len, c_u.c); if (dlen > 0) { c_u.c->tseq += dlen; } } } if (c_u.c->m_tstamp == 0 || c_u.c->t_tstamp == 0) { c_u.c->m_tstamp=0; c_u.c->t_tstamp=0; } else { c_u.c->m_tstamp++; /* XXX good enough for testing */ } if (dlen < c_u.c->window) c_u.c->window -= dlen; if (r->type & TH_RST) { c_u.c->status=U_TCP_CLOSE; s->stats.stream_remote_abort++; a_conns--; } switch (c_u.c->status) { case U_TCP_ESTABLISHED: if (r->type & TH_PSH) { w_u.ptr=xmalloc(sizeof(send_pri_workunit_t)); w_u.w->magic=PRI_4SEND_MAGIC; w_u.w->dhost=dhost; w_u.w->dport=dport; w_u.w->sport=sport; w_u.w->shost=c_u.c->send_ip; w_u.w->tseq=c_u.c->tseq; w_u.w->mseq=c_u.c->mseq; w_u.w->window_size=c_u.c->window; w_u.w->flags=TH_ACK|TH_FIN; w_u.w->doff=0; w_u.w->t_tstamp=c_u.c->t_tstamp; w_u.w->m_tstamp=c_u.c->m_tstamp; c_u.c->m_tstamp++; DBG(M_CON, "setting connection state into FIN_WAIT2 and sending ACK|FIN"); c_u.c->status=U_TCP_FIN_WAIT2; fifo_push(pri_work, w_u.ptr); s->stats.stream_segments_sent++; c_u.c->mseq++; w_u.ptr=NULL; } else if (r->type & TH_FIN) { c_u.c->tseq += 1; /* FIN eats a seq ;] */ w_u.ptr=xmalloc(sizeof(send_pri_workunit_t)); w_u.w->magic=PRI_4SEND_MAGIC; w_u.w->dhost=dhost; w_u.w->dport=dport; w_u.w->sport=sport; w_u.w->shost=c_u.c->send_ip; w_u.w->tseq=c_u.c->tseq; w_u.w->mseq=c_u.c->mseq; w_u.w->window_size=c_u.c->window; w_u.w->flags=TH_ACK; w_u.w->doff=0; w_u.w->t_tstamp=c_u.c->t_tstamp; w_u.w->m_tstamp=c_u.c->m_tstamp; DBG(M_CON, "acking FIN"); fifo_push(pri_work, w_u.ptr); s->stats.stream_segments_sent++; w_u.ptr=xmalloc(sizeof(send_pri_workunit_t)); w_u.w->magic=PRI_4SEND_MAGIC; w_u.w->dhost=dhost; w_u.w->dport=dport; w_u.w->sport=sport; w_u.w->shost=c_u.c->send_ip; w_u.w->tseq=c_u.c->tseq; w_u.w->mseq=c_u.c->mseq; w_u.w->window_size=c_u.c->window; w_u.w->flags=TH_ACK|TH_FIN; w_u.w->doff=0; w_u.w->t_tstamp=c_u.c->t_tstamp; w_u.w->m_tstamp=c_u.c->m_tstamp; c_u.c->m_tstamp++; DBG(M_CON, "setting connection into state closed and sending ACK|FIN"); fifo_push(pri_work, w_u.ptr); s->stats.stream_segments_sent++; c_u.c->status=U_TCP_CLOSE; fifo_push(pri_work, w_u.ptr); s->stats.stream_segments_sent++; w_u.ptr=NULL; c_u.c->mseq++; a_conns--; } break; /* U_TCP_ESTABLISHED: */ case U_TCP_CLOSE: if (r->type == TH_ACK) { break; } DBG(M_CON, "reseting a packet type %s (no connection entry)", strtcpflgs(r->type)); s->stats.stream_closed_alien_pkt++; w_u.ptr=xmalloc(sizeof(send_pri_workunit_t)); w_u.w->magic=PRI_4SEND_MAGIC; w_u.w->dhost=dhost; w_u.w->dport=dport; w_u.w->sport=sport; w_u.w->shost=c_u.c->send_ip; w_u.w->tseq=c_u.c->tseq; w_u.w->mseq=c_u.c->mseq; w_u.w->window_size=c_u.c->window; w_u.w->flags=TH_RST; w_u.w->doff=0; w_u.w->t_tstamp=c_u.c->t_tstamp; w_u.w->m_tstamp=c_u.c->m_tstamp; c_u.c->m_tstamp++; DBG(M_CON, "reseting packed to closed connection"); fifo_push(pri_work, w_u.ptr); s->stats.stream_segments_sent++; w_u.ptr=NULL; break; /* U_TCP_CLOSE */ case U_TCP_FIN_WAIT2: if (r->type & TH_FIN) { /* ok its closed both ways, lets ack the fin and be done with it */ c_u.c->tseq += 1; w_u.ptr=xmalloc(sizeof(send_pri_workunit_t)); w_u.w->magic=PRI_4SEND_MAGIC; w_u.w->dhost=dhost; w_u.w->dport=dport; w_u.w->sport=sport; w_u.w->shost=c_u.c->send_ip; w_u.w->tseq=c_u.c->tseq; w_u.w->mseq=c_u.c->mseq; w_u.w->window_size=c_u.c->window; w_u.w->flags=TH_ACK; w_u.w->doff=0; w_u.w->t_tstamp=c_u.c->t_tstamp; w_u.w->m_tstamp=c_u.c->m_tstamp; c_u.c->m_tstamp++; c_u.c->status=U_TCP_CLOSE; fifo_push(pri_work, w_u.ptr); s->stats.stream_segments_sent++; w_u.ptr=NULL; DBG(M_CON, "Setting connection to closed and acking final fin"); } break; /* U_TCP_FIN_WAIT2 */ # if 0 if (r->type & (TH_ACK|TH_SYN)) { } break; case U_TCP_FIN_WAIT1: case U_TCP_FIN_WAIT2: case U_TCP_CLOSING: case U_TCP_TIME_WAIT: case U_TCP_CLOSE_WAIT: case U_TCP_LAST_ACK: case U_TCP_CLOSE: # endif default: ERR("I have no code. I have no code"); break; } } /* found in state table */ else if ((r->type & (TH_ACK|TH_SYN)) == (TH_ACK|TH_SYN)) { /* should it be in state table */ DBG(M_CON, "Connection with flags %s", strtcpflgs(r->type)); /* yes this is a new connection */ c_u.ptr=xmalloc(sizeof(connection_status_t)); memset(c_u.ptr, 0, sizeof(connection_status_t)); c_u.c->status=U_TCP_ESTABLISHED; c_u.c->send_ip=shost; /* Our IP */ c_u.c->recv_len=0; c_u.c->send_len=0; c_u.c->send_buf=NULL; c_u.c->recv_buf=NULL; c_u.c->recv_stseq=0; c_u.c->tseq=r->tseq; c_u.c->mseq=r->mseq; c_u.c->window=r->window_size; /* XXX wscale */ c_u.c->t_tstamp=r->t_tstamp; c_u.c->m_tstamp=r->m_tstamp; c_u.c->ack_pending=1; if (GET_IMMEDIATE()) { ia.s_addr=shost; snprintf(shost_s, sizeof(shost_s) -1, "%s", inet_ntoa(ia)); ia.s_addr=dhost; VRB(0, "connected %s:%u -> %s:%u", shost_s, sport, inet_ntoa(ia), dport); } s->stats.stream_connections_est++; rbinsert(state_tbl, state_key, c_u.ptr); a_conns++; send_connect(state_key, c_u.c, pri_work, r); } /* looks like something we want to connect to ;] */ else { s->stats.stream_completely_alien_packet++; DBG(M_CON, "ignoring packet with flags %s", strtcpflgs(r->type)); } return; }
void i2p_stream::read_line(error_code const& e, boost::shared_ptr<handler_type> h) { TORRENT_ASSERT(m_magic == 0x1337); #if defined TORRENT_ASIO_DEBUGGING complete_async("i2p_stream::read_line"); #endif if (handle_error(e, h)) return; int read_pos = m_buffer.size(); // look for \n which means end of the response if (m_buffer[read_pos - 1] != '\n') { #if defined TORRENT_ASIO_DEBUGGING add_outstanding_async("i2p_stream::read_line"); #endif // read another byte from the socket m_buffer.resize(read_pos + 1); async_read(m_sock, boost::asio::buffer(&m_buffer[read_pos], 1) , boost::bind(&i2p_stream::read_line, this, _1, h)); return; } m_buffer[read_pos - 1] = 0; if (m_command == cmd_incoming) { // this is the line containing the destination // of the incoming connection in an accept call m_dest = &m_buffer[0]; (*h)(e); std::vector<char>().swap(m_buffer); return; } error_code invalid_response(i2p_error::parse_failed , get_i2p_category()); // null-terminate the string and parse it m_buffer.push_back(0); char* ptr = &m_buffer[0]; char* next = ptr; char const* expect1 = 0; char const* expect2 = 0; switch (m_state) { case read_hello_response: expect1 = "HELLO"; expect2 = "REPLY"; break; case read_connect_response: case read_accept_response: expect1 = "STREAM"; expect2 = "STATUS"; break; case read_session_create_response: expect1 = "SESSION"; expect2 = "STATUS"; break; case read_name_lookup_response: expect1 = "NAMING"; expect2 = "REPLY"; break; } // fprintf(stderr, "<<< %s\n", &m_buffer[0]); ptr = string_tokenize(next, ' ', &next); if (ptr == 0 || expect1 == 0 || strcmp(expect1, ptr)) { handle_error(invalid_response, h); return; } ptr = string_tokenize(next, ' ', &next); if (ptr == 0 || expect2 == 0 || strcmp(expect2, ptr)) { handle_error(invalid_response, h); return; } int result = 0; // char const* message = 0; // float version = 3.0f; for(;;) { char* name = string_tokenize(next, '=', &next); if (name == 0) break; // fprintf(stderr, "name=\"%s\"\n", name); char* ptr2 = string_tokenize(next, ' ', &next); if (ptr2 == 0) { handle_error(invalid_response, h); return; } // fprintf(stderr, "value=\"%s\"\n", ptr2); if (strcmp("RESULT", name) == 0) { if (strcmp("OK", ptr2) == 0) result = i2p_error::no_error; else if (strcmp("CANT_REACH_PEER", ptr2) == 0) result = i2p_error::cant_reach_peer; else if (strcmp("I2P_ERROR", ptr2) == 0) result = i2p_error::i2p_error; else if (strcmp("INVALID_KEY", ptr2) == 0) result = i2p_error::invalid_key; else if (strcmp("INVALID_ID", ptr2) == 0) result = i2p_error::invalid_id; else if (strcmp("TIMEOUT", ptr2) == 0) result = i2p_error::timeout; else if (strcmp("KEY_NOT_FOUND", ptr2) == 0) result = i2p_error::key_not_found; else if (strcmp("DUPLICATED_ID", ptr2) == 0) result = i2p_error::duplicated_id; else result = i2p_error::num_errors; // unknown error } else if (strcmp("MESSAGE", name) == 0) { // message = ptr2; } else if (strcmp("VERSION", name) == 0) { // version = float(atof(ptr2)); } else if (strcmp("VALUE", name) == 0) { m_name_lookup = ptr2; } else if (strcmp("DESTINATION", name) == 0) { m_dest = ptr2; } } error_code ec(result, get_i2p_category()); switch (result) { case i2p_error::no_error: case i2p_error::invalid_key: break; default: { handle_error (ec, h); return; } } switch (m_state) { case read_hello_response: switch (m_command) { case cmd_create_session: send_session_create(h); break; case cmd_accept: send_accept(h); break; case cmd_connect: send_connect(h); break; default: (*h)(e); std::vector<char>().swap(m_buffer); } break; case read_connect_response: case read_session_create_response: case read_name_lookup_response: (*h)(ec); std::vector<char>().swap(m_buffer); break; case read_accept_response: // the SAM bridge is waiting for an incoming // connection. // wait for one more line containing // the destination of the remote peer m_command = cmd_incoming; m_buffer.resize(1); #if defined TORRENT_ASIO_DEBUGGING add_outstanding_async("i2p_stream::read_line"); #endif async_read(m_sock, boost::asio::buffer(m_buffer) , boost::bind(&i2p_stream::read_line, this, _1, h)); break; } return; }
void adbd_auth_verified(atransport* t) { LOG(INFO) << "adb client authorized"; handle_online(t); send_connect(t); }
void handle_packet(apacket *p, atransport *t) { asocket *s; D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0], ((char*) (&(p->msg.command)))[1], ((char*) (&(p->msg.command)))[2], ((char*) (&(p->msg.command)))[3]); print_packet("recv", p); switch(p->msg.command){ case A_SYNC: if(p->msg.arg0){ send_packet(p, t); if(HOST) send_connect(t); } else { t->connection_state = CS_OFFLINE; handle_offline(t); send_packet(p, t); } return; case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */ /* XXX verify version, etc */ if(t->connection_state != CS_OFFLINE) { t->connection_state = CS_OFFLINE; handle_offline(t); } parse_banner((char*) p->data, t); handle_online(t); send_connect(t); break; case A_OPEN: /* OPEN(local-id, 0, "destination") */ if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) { char *name = (char*) p->data; name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0; s = create_local_service_socket(name); if(s == 0) { send_close(0, p->msg.arg0, t); } else { s->peer = create_remote_socket(p->msg.arg0, t); s->peer->peer = s; send_ready(s->id, s->peer->id, t); s->ready(s); } } break; case A_OKAY: /* READY(local-id, remote-id, "") */ if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) { if((s = find_local_socket(p->msg.arg1, 0))) { if(s->peer == 0) { /* On first READY message, create the connection. */ s->peer = create_remote_socket(p->msg.arg0, t); s->peer->peer = s; s->ready(s); } else if (s->peer->id == p->msg.arg0) { /* Other READY messages must use the same local-id */ s->ready(s); } else { D("Invalid A_OKAY(%d,%d), expected A_OKAY(%d,%d) on transport %s\n", p->msg.arg0, p->msg.arg1, s->peer->id, p->msg.arg1, t->serial); } } } break; case A_CLSE: /* CLOSE(local-id, remote-id, "") */ if (t->online && p->msg.arg1 != 0) { if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) { /* According to protocol.txt, p->msg.arg0 might be 0 to indicate * a failed OPEN only. However, due to a bug in previous ADB * versions, CLOSE(0, remote-id, "") was also used for normal * CLOSE() operations. * * This is bad because it means a compromised adbd could * send packets to close connections between the host and * other devices. To avoid this, only allow this if the local * socket has a peer on the same transport. */ if (p->msg.arg0 == 0 && s->peer && s->peer->transport != t) { D("Invalid A_CLSE(0, %u) from transport %s, expected transport %s\n", p->msg.arg1, t->serial, s->peer->transport->serial); } else { s->close(s); } } } break; case A_WRTE: if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) { if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) { unsigned rid = p->msg.arg0; p->len = p->msg.data_length; if(s->enqueue(s, p) == 0) { D("Enqueue the socket\n"); send_ready(s->id, rid, t); } return; } } break; default: printf("handle_packet: what is %08x?!\n", p->msg.command); } put_apacket(p); }
static void test_send_connect(void) { /* /connect [(host) | (host:port) | (host port)] */ /* No args, connected, should issue an error message */ server_connect__called__ = 0; server_connect__host__ = NULL; server_connect__port__ = NULL; *err = 0; mock_s.soc = 1; /* Non-negative socket implies connected */ char str1[] = ""; send_connect(err, str1, c); assert_equals(server_connect__called__, 0); assert_strcmp(err, "Error: Already connected or reconnecting to server"); /* No args, not connected, should attempt to reconnect on the current server */ server_connect__called__ = 0; server_connect__host__ = NULL; server_connect__port__ = NULL; mock_s.soc = -1; /* -1 socket implies not connected */ char str2[] = ""; send_connect(err, str2, c); assert_equals(server_connect__called__, 1); assert_strcmp(server_connect__host__, "mock-host"); assert_strcmp(server_connect__port__, "mock-port"); /* <server> */ server_connect__called__ = 0; server_connect__host__ = NULL; server_connect__port__ = NULL; char str3[] = "server.tld"; send_connect(err, str3, c); assert_equals(server_connect__called__, 1); assert_strcmp(server_connect__host__, "server.tld"); assert_strcmp(server_connect__port__, "6667"); /* <server>:<port> */ server_connect__called__ = 0; server_connect__host__ = NULL; server_connect__port__ = NULL; char str4[] = "server.tld:123"; send_connect(err, str4, c); assert_equals(server_connect__called__, 1); assert_strcmp(server_connect__host__, "server.tld"); assert_strcmp(server_connect__port__, "123"); /* <server> <port> */ server_connect__called__ = 0; server_connect__host__ = NULL; server_connect__port__ = NULL; char str5[] = "server.tld 123"; send_connect(err, str5, c); assert_equals(server_connect__called__, 1); assert_strcmp(server_connect__host__, "server.tld"); assert_strcmp(server_connect__port__, "123"); }