void recv_data(int len) { static i32 i; static u32 buffer[4]; const __builtin_quad *b = (__builtin_quad *)buffer; i32 tout; while (len >= 4) { tout = 0x1000; buffer[i] = (u32)(RECEIVE_NETWORK_B() & 0xFF) << 24 | (u32)(RECEIVE_NETWORK_B() & 0xFF) << 16 | (u32)(RECEIVE_NETWORK_B() & 0xFF) << 8 | (u32)(RECEIVE_NETWORK_B() & 0xFF); i = (i + 1) % 4; if (i == 0) { while (!link_ready() && --tout) { asm("nop;nop;nop;nop;;"); } if (tout) { link_send(b); } } if (tout) { len -= 4; } else { len = 0; } } }
// send current handshake link_t link_sync(link_t link) { if(!link) return LOG("bad args"); if(!link->x) return LOG("no exchange"); if(!link->send_cb) return LOG("no network"); return link_send(link, link_handshake(link)); }
// process any outgoing packets for this channel, optionally send given packet too link_t link_flush(link_t link, channel3_t c3, lob_t inner) { if(!link || !c3) return LOG("bad args"); if(inner) channel3_send(c3, inner); while((inner = channel3_sending(c3))) { link_send(link, exchange3_send(link->x, inner)); lob_free(inner); } // TODO if channel is now ended, remove from link->index return link; }
// encrypt and send this one packet on this pipe link_t link_direct(link_t link, lob_t inner) { if(!link || !inner) return LOG("bad args"); if(!link->send_cb) { LOG_WARN("no network, dropping %s",lob_json(inner)); return NULL; } // add an outgoing cid if none set if(!lob_get_int(inner,"c")) lob_set_uint(inner,"c",e3x_exchange_cid(link->x, NULL)); lob_t outer = e3x_exchange_send(link->x, inner); lob_free(inner); return link_send(link, outer); }
// process any outgoing packets for this channel, optionally send given packet too link_t link_flush(link_t link, e3x_channel_t c3, lob_t inner) { if(!link || !c3) return LOG("bad args"); if(inner) e3x_channel_send(c3, inner); while((inner = e3x_channel_sending(c3))) { LOG("\t--> %s",lob_json(inner)); link_send(link, e3x_exchange_send(link->x, inner)); lob_free(inner); } // TODO if channel is now ended, remove from link->index return link; }
/*thread que recebe da camada de baixo*/ PRIVATE void *internalsend(void *param) { int isfragmentable; int mtu; uint16_t count_id = 0; wait_list_item_t intern_list_cons; offsetlst_t *head = NULL,*aux; datagram_t *data_send = ALLOC(datagram_t, sizeof(datagram_t)); byte *buffer; while(TRUE) { intern_list_cons = wait_list_remove(); //getmtu do destino mtu = getmtu(num_global, intern_list_cons.first_dest_link); //protocolo = 1 utilizado pelo transp ou protocolo = 0 utilizado pela tab de rotas if(intern_list_cons.protocol == 1 || intern_list_cons.protocol == 0) { isfragmentable = fragpack(&head,intern_list_cons.data,intern_list_cons.size,mtu,intern_list_cons.offset); LOG("dest1 %d", intern_list_cons.dest); //sabe que é apenas dados if(isfragmentable == 0) { //nao precisou fragmentar data_send->size = intern_list_cons.size; data_send->id = count_id; data_send->frag = intern_list_cons.offset; data_send->protocol = intern_list_cons.protocol; data_send->ttl = intern_list_cons.ttl; data_send->dest = intern_list_cons.dest; data_send->src = intern_list_cons.src; data_send->data = ALLOC(byte, data_send->size); memcpy(data_send->data, intern_list_cons.data, data_send->size); buffer = ALLOC(byte, data_send->size + NET_HEADER_SIZE); buildsenddatagram(buffer,data_send); free(data_send->data); if(count_id <= 65535) count_id++; else count_id = 0; LOG("enviando para enlace"); link_send(intern_list_cons.first_dest_link, buffer, data_send->size + NET_HEADER_SIZE); //free(data_send); ??? } else {LOG("frag para enlace"); while(head != NULL) {LOG("head para enlace"); //precisa fragmentar data_send->size = head->datagram->size; data_send->id = count_id; data_send->frag = head->datagram->frag; data_send->protocol = intern_list_cons.protocol; data_send->ttl = intern_list_cons.ttl; data_send->dest = intern_list_cons.dest; LOG("dest %d", data_send->dest); data_send->src = intern_list_cons.src; data_send->data = ALLOC(byte, head->datagram->size); memcpy(data_send->data, head->datagram->data, head->datagram->size); LOG("enviando data %s", data_send->data); buffer = ALLOC(byte, data_send->size + NET_HEADER_SIZE); buildsenddatagram(buffer,data_send); free(data_send->data); link_send(intern_list_cons.first_dest_link, buffer, data_send->size + NET_HEADER_SIZE); //anda com a lista aux = head; head = head->next; free(aux); } LOG("fim para enlace"); if(count_id <= 65535) count_id++; else count_id = 0; } } //protocolo = 2 , utilizado pelo repasse else { if(intern_list_cons.protocol == 2) { isfragmentable = fragpack2(&head,intern_list_cons.data,intern_list_cons.size,mtu,intern_list_cons.offset); if(isfragmentable == 0) { //nao precisou fragmentar data_send->size = intern_list_cons.size; data_send->id = intern_list_cons.id; data_send->frag = intern_list_cons.offset; data_send->protocol = intern_list_cons.protocol; data_send->ttl = intern_list_cons.ttl; data_send->dest = intern_list_cons.dest; data_send->src = intern_list_cons.src; data_send->data = ALLOC(byte, data_send->size); memcpy(data_send->data, intern_list_cons.data, data_send->size); buffer = ALLOC(byte, data_send->size + NET_HEADER_SIZE); buildsenddatagram(buffer,data_send); free(data_send->data); LOG("enviando para enlace"); link_send(intern_list_cons.first_dest_link, buffer, data_send->size + NET_HEADER_SIZE); //free(data_send); ??? } else { while(head != NULL) { //precisa fragmentar data_send->size = head->datagram->size; data_send->id = intern_list_cons.id; data_send->frag = head->datagram->frag; data_send->protocol = intern_list_cons.protocol; data_send->ttl = intern_list_cons.ttl; data_send->dest = intern_list_cons.dest; data_send->src = intern_list_cons.src; data_send->data = ALLOC(byte, head->datagram->size); memcpy(data_send->data, head->datagram->data, head->datagram->size); buffer = ALLOC(byte, data_send->size + NET_HEADER_SIZE); buildsenddatagram(buffer,data_send); free(data_send->data); link_send(intern_list_cons.first_dest_link, buffer, data_send->size + NET_HEADER_SIZE); //anda com a lista aux = head; head = head->next; free(aux); } } } } } }
/* Send a sequence of bytes over the virtual link * On error: Throws a Byte Exception */ void link_send_bytes(CPU_t *cpu, void *data, size_t length) { size_t i; for (i = 0; i < length; i++) link_send(cpu, ((u_char*) data)[i]); }
// processes incoming packet, it will take ownership of p link_t mesh_receive(mesh_t mesh, lob_t outer, pipe_t pipe) { lob_t inner; link_t link; char token[17]; hashname_t id; if(!mesh || !outer || !pipe) return LOG("bad args"); LOG("mesh receiving %s to %s via pipe %s",outer->head_len?"handshake":"channel",hashname_short(mesh->id),pipe->id); // process handshakes if(outer->head_len == 1) { inner = e3x_self_decrypt(mesh->self, outer); if(!inner) { LOG("%02x handshake failed %s",outer->head[0],e3x_err()); lob_free(outer); return NULL; } // couple the two together, inner->outer lob_link(inner,outer); // set the unique id string based on some of the first 16 (routing token) bytes in the body base32_encode(outer->body,10,token,17); lob_set(inner,"id",token); // process the handshake return mesh_receive_handshake(mesh, inner, pipe); } // handle channel packets if(outer->head_len == 0) { if(outer->body_len < 16) { LOG("packet too small %d",outer->body_len); lob_free(outer); return NULL; } route_t route; for(route = mesh->routes;route;route = route->next) if(memcmp(route->token,outer->body,8) == 0) break; link = route ? route->link : NULL; if(!link) { LOG("dropping, no link for token %s",util_hex(outer->body,16,NULL)); lob_free(outer); return NULL; } // forward packet if(!route->flag) { LOG("forwarding route token %s via %s len %d",util_hex(route->token,8,NULL),hashname_short(link->id),lob_len(outer)); return link_send(link, outer); } inner = e3x_exchange_receive(link->x, outer); lob_free(outer); if(!inner) return LOG("channel decryption fail for link %s %s",hashname_short(link->id),e3x_err()); LOG("channel packet %d bytes from %s",lob_len(inner),hashname_short(link->id)); return link_receive(link,inner,pipe); } // transform incoming bare link json format into handshake for discovery if((inner = lob_get_json(outer,"keys"))) { if((id = hashname_vkeys(inner))) { lob_set(outer,"hashname",hashname_char(id)); lob_set_int(outer,"at",0); lob_set(outer,"type","link"); LOG("bare incoming link json being discovered %s",lob_json(outer)); } lob_free(inner); } // run everything else through discovery, usually plain handshakes mesh_discover(mesh, outer, pipe); link = mesh_linked(mesh, lob_get(outer,"hashname"), 0); lob_free(outer); return link; }