static dbms_error_t i_comms( dbms * me, int token, int *retval, DBT * v1, DBT * v2, DBT * r1, DBT * r2 ) { int err = 0; DBT rr1, rr2; struct header cmd; struct iovec iov[3]; struct msghdr msg; size_t s; if (retval) *retval = -1; rr1.data = rr2.data = NULL; cmd.token = token | F_CLIENT_SIDE; cmd.len1 = htonl((v1 == NULL) ? 0 : v1->size); cmd.len2 = htonl((v2 == NULL) ? 0 : v2->size); iov[0].iov_base = (char *) &cmd; iov[0].iov_len = sizeof(cmd); iov[1].iov_base = (v1 == NULL) ? NULL : v1->data; iov[1].iov_len = (v1 == NULL) ? 0 : v1->size; iov[2].iov_base = (v2 == NULL) ? NULL : v2->data; iov[2].iov_len = (v2 == NULL) ? 0 : v2->size; #ifdef STATIC_CS_BUFF if (iov[0].iov_len + iov[1].iov_len + iov[2].iov_len > MAX_CS_PAYLOAD) return E_TOOBIG; #endif msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = iov; msg.msg_iovlen = 3; /* temporal fix to make CYGWN compile the basic thing - need better solution */ #ifndef RDFSTORE_PLATFORM_CYGWIN msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_flags = 0; #endif s = sendmsg(me->sockfd, &msg, 0); if (s == 0) { err = E_CLOSE; goto retry_com; } else if (s < 0) { mark_dbms_error(me, "sendmsg()", errno); err = E_ERROR; goto retry_com; } else if (s != iov[0].iov_len + iov[1].iov_len + iov[2].iov_len) { err = E_FULLWRITE; goto exit_com; }; s = recv(me->sockfd, &cmd, sizeof(cmd), 0); if (s == 0) { err = E_CLOSE; goto retry_com; } else if (s < 0) { mark_dbms_error(me, "header-recv()", errno); err = E_ERROR; goto retry_com; } else if (s != sizeof(cmd)) { err = E_FULLREAD; goto exit_com; }; cmd.len1 = ntohl(cmd.len1); cmd.len2 = ntohl(cmd.len2); rr2.data = rr1.data = NULL; if ((err = getpack(me, cmd.len1, r1 ? r1 : &rr1)) != 0) goto retry_com; if ((err = getpack(me, cmd.len2, r2 ? r2 : &rr2)) != 0) goto retry_com; if ((cmd.token & MASK_TOKEN) == TOKEN_ERROR) { char *d = NULL; int l = 0; if (r1) { l = r1->size; d = r1->data; } else { l = rr1.size; d = rr1.data; }; errno = 0; if ((d) && (l > 0)) { d[l] = '\0'; } else { d = "DBMS side errror, no cause reported"; }; err = E_ERROR; errno = 0; set_dbms_error(me, d, err); goto exit_com; } else if (((cmd.token & MASK_TOKEN) != token) || ((cmd.token | F_SERVER_SIDE) == 0)) { err = E_PROTO; goto exit_com; }; if ((rr1.data != NULL) && (rr1.size)) { (*me->free) (rr1.data); rr1.size = 0; }; if ((rr2.data != NULL) && (rr2.size)) { (*me->free) (rr2.data); rr1.size = 0; }; if ((cmd.token & MASK_STATUS) == F_FOUND) { if (retval) *retval = 0; } else { if (retval) *retval = 1; if (r1 != NULL) { if ((r1->size) && (r1->size)) (*me->free) (r1->data); r1->data = NULL; r1->size = 0; }; if (r2 != NULL) { if ((r2->size) && (r2->size)) (*me->free) (r2->data); r2->data = NULL; r2->size = 0; }; }; err = 0; goto done_com; retry_com: exit_com: if ((r1 != NULL) && (r1->data != NULL) && (r1->size != 0)) { (*me->free) (r1->data); r1->size = 0; }; if ((r2 != NULL) && (r2->data != NULL) && (r2->size != 0)) { (*me->free) (r2->data); r2->size = 0; }; if ((rr1.data != NULL) && (rr1.size)) { (*me->free) (rr1.data); rr1.size = 0; }; if ((rr2.data != NULL) && (rr1.size)) { (*me->free) (rr2.data); rr2.size = 0; }; done_com: return err; }
/*thread que recebe da camada de baixo*/ PRIVATE void *internalrecv(void *param) { datagram_t *recv; pthread_t recv_route_thread; packlst_t *list = NULL; uint16_t rcv_checksum; byte *buf; size_t size; size_t data_size; while(TRUE) { rcv_checksum = 1; //espera por liberação da camada de enlace para o próximo recebimento LOG("mutex travado para receber"); pthread_mutex_lock(&net_recv_mutex); //copia dados recebidos pelo enlace buf = recv_frame.data; size = recv_frame.size; //libera camada de enlace para o proximo recebimento LOG("mutex liberado para camada de enlace"); pthread_mutex_unlock(&link_recv_mutex); //criação do datagram_t recv = buildrecvdatagram(buf, size); LOG("recebendo data %s", recv->data); //recv = ALLOC(datagram_t, sizeof(datagram_t)); //recv->data = ALLOC(byte, size - NET_HEADER_SIZE); //memcpy(recv, buf, NET_HEADER_SIZE - CHECKSUM_SIZE); //memcpy(recv->data, buf + NET_HEADER_SIZE - CHECKSUM_SIZE, size - NET_HEADER_SIZE); //memcpy(&recv->checksum, buf + size - CHECKSUM_SIZE, CHECKSUM_SIZE); //calcula o checksum //LOG("check: %u",recv->checksum); rcv_checksum = checksum(buf, size - CHECKSUM_SIZE); //LOG("checksum calculado: %#04x", rcv_checksum); rcv_checksum = rcv_checksum - recv->checksum; //LOG("resultado do checksum: %#04x", rcv_checksum); //desaloca buf free(buf); buf = NULL; //se o checksum estiver correto if (!rcv_checksum) {LOG("dest %d %d ", recv->dest, num_global); //se o destino é para mim if(recv->dest == num_global) {LOG("pack para mim"); //adiciona na lista e se tiver completo trata o pacote if(insertoffset(&list, recv) == TRUE) { if(list == NULL) LOG("Esta 222 NULL ---------"); LOG("insertoffset ok!"); //tratar pacote recv->data = getpack(&list, recv->id, recv->src, &data_size); LOG("get pack"); LOG("recv->data %s", recv->data); switch(recv->protocol) { case 0: //mensagem de rotas pthread_create(&recv_route_thread, NULL, internalhandleroute, recv->data); pthread_detach(recv_route_thread); free(recv); break; case 1: //PTC case 2: //repassa o pacote para camada de transporte //espera por liberação da camada de transporte para o próximo recebimento pthread_mutex_lock(&net2_recv_mutex); LOG("mutex travado para repassar a camada de transporte"); recv_datagram.data = recv->data; recv_datagram.size = data_size; recv_datagram.src = recv->src; LOG("data: %s", recv_datagram.data); LOG("data: %zu", recv_datagram.size); free(recv); //libera camada de transporte para pegar o pacote LOG("mutex liberado para camada de transporte"); pthread_mutex_unlock(&transp_recv_mutex); break; } } } else //senão reenvia pacote {LOG("pack nao e para mim"); //reenviar pacote recv->protocol = 2; recv->ttl--; net_resend(recv); } } } }