int sr_vns_read_from_server(struct sr_instance* sr /* borrowed */) { int command, len; unsigned char *buf = 0; c_packet_ethernet_header* sr_pkt = 0; int ret = 0, bytes_read = 0; /* REQUIRES */ assert(sr); /*--------------------------------------------------------------------------- Read a command from the server -------------------------------------------------------------------------*/ bytes_read = 0; /* attempt to read the size of the incoming packet */ while( bytes_read < 4) { do { /* -- just in case SIGALRM breaks recv -- */ errno = 0; /* -- hacky glibc workaround -- */ if((ret = recv(sr->sockfd,((uint8_t*)&len) + bytes_read, 4 - bytes_read, 0)) == -1) { if ( errno == EINTR ) { continue; } perror("recv(..):sr_client.c::sr_vns_read_from_server"); return -1; } bytes_read += ret; } while ( errno == EINTR); /* be mindful of signals */ } len = ntohl(len); if ( len > 10000 || len < 0 ) { fprintf(stderr,"Error: command length to large %d\n",len); close(sr->sockfd); return -1; } if((buf = (unsigned char*)malloc(len)) == 0) { fprintf(stderr,"Error: out of memory (sr_vns_read_from_server)\n"); return -1; } /* set first field of command since we've already read it */ *((int *)buf) = htonl(len); bytes_read = 0; /* read the rest of the command */ while ( bytes_read < len - 4) { do {/* -- just in case SIGALRM breaks recv -- */ errno = 0; /* -- hacky glibc workaround -- */ if ((ret = read(sr->sockfd, buf+4+bytes_read, len - 4 - bytes_read)) == -1) { if ( errno == EINTR ) { continue; } fprintf(stderr,"Error: failed reading command body %d\n",ret); close(sr->sockfd); return -1; } bytes_read += ret; } while (errno == EINTR); /* be mindful of signals */ } /* My entry for most unreadable line of code - guido */ /* ... you win - mc */ command = *(((int *)buf)+1) = ntohl(*(((int *)buf)+1)); switch (command) { /* ------------- VNSPACKET -------------------- */ case VNSPACKET: sr_pkt = (c_packet_ethernet_header *)buf; /* -- log packet -- */ sr_log_packet(sr, buf + sizeof(c_packet_header), ntohl(sr_pkt->mLen) - sizeof(c_packet_header)); /* -- pass to router, student's code should take over here -- */ sr_integ_input(sr, (buf+sizeof(c_packet_header)), /* lent */ len - sizeof(c_packet_header), (const char*)buf + sizeof(c_base)); /* lent */ break; /* ------------- VNSCLOSE -------------------- */ case VNSCLOSE: fprintf(stderr,"vns server closed session.\n"); fprintf(stderr,"Reason: %s\n",((c_close*)buf)->mErrorMessage); sr_close_instance(sr); sr_integ_close(sr); if(buf) { free(buf); } return 0; break; /* ------------- VNSHWINFO -------------------- */ case VNSHWINFO: sr_handle_hwinfo(sr,(c_hwinfo*)buf); break; default: Debug("unknown command: %d\n", command); break; } if(buf) { free(buf); } return 1; }/* -- sr_vns_read_from_server -- */
int sr_read_from_server_expect(struct sr_instance* sr /* borrowed */, int expected_cmd) { int command, len; unsigned char *buf = 0; c_packet_ethernet_header* sr_pkt = 0; int ret = 0, bytes_read = 0; /* REQUIRES */ assert(sr); /*--------------------------------------------------------------------------- Read a command from the server -------------------------------------------------------------------------*/ bytes_read = 0; /* attempt to read the size of the incoming packet */ while( bytes_read < 4) { do { /* -- just in case SIGALRM breaks recv -- */ errno = 0; /* -- hacky glibc workaround -- */ if((ret = recv(sr->sockfd,((uint8_t*)&len) + bytes_read, 4 - bytes_read, 0)) == -1) { if ( errno == EINTR ) { continue; } perror("recv(..):sr_client.c::sr_read_from_server"); return -1; } bytes_read += ret; } while ( errno == EINTR); /* be mindful of signals */ } len = ntohl(len); if ( len > 10000 || len < 0 ) { fprintf(stderr,"Error: command length to large %d\n",len); close(sr->sockfd); return -1; } if((buf = (unsigned char*)malloc(len)) == 0) { fprintf(stderr,"Error: out of memory (sr_read_from_server)\n"); return -1; } /* set first field of command since we've already read it */ *((int *)buf) = htonl(len); bytes_read = 0; /* read the rest of the command */ while ( bytes_read < len - 4) { do {/* -- just in case SIGALRM breaks recv -- */ errno = 0; /* -- hacky glibc workaround -- */ if ((ret = read(sr->sockfd, buf+4+bytes_read, len - 4 - bytes_read)) == -1) { if ( errno == EINTR ) { continue; } fprintf(stderr,"Error: failed reading command body %d\n",ret); close(sr->sockfd); return -1; } bytes_read += ret; } while (errno == EINTR); /* be mindful of signals */ } /* My entry for most unreadable line of code - guido */ /* ... you win - mc */ command = *(((int *)buf)+1) = ntohl(*(((int *)buf)+1)); /* make sure the command is what we expected if we were expecting something */ if(expected_cmd && command!=expected_cmd) { if(command != VNSCLOSE) { /* VNSCLOSE is always ok */ fprintf(stderr, "Error: expected command %d but got %d\n", expected_cmd, command); return -1; } } ret = 1; switch (command) { /* ------------- VNSPACKET -------------------- */ case VNSPACKET: sr_pkt = (c_packet_ethernet_header *)buf; /* -- log packet -- */ sr_log_packet(sr, buf + sizeof(c_packet_header), ntohl(sr_pkt->mLen) - sizeof(c_packet_header)); /* -- pass to router, student's code should take over here -- */ sr_integ_input(sr, (buf+sizeof(c_packet_header)), /* lent */ len - sizeof(c_packet_header), (const char*)buf + sizeof(c_base)); /* lent */ break; /* ------------- VNSCLOSE -------------------- */ case VNSCLOSE: fprintf(stderr,"VNS server closed session.\n"); fprintf(stderr,"Reason: %s\n",((c_close*)buf)->mErrorMessage); sr_close_instance(sr); /* closes the VNS socket and logfile */ if(buf) { free(buf); } return 0; break; /* ------------- VNSBANNER -------------------- */ case VNSBANNER: fprintf(stderr,"%s",((c_banner*)buf)->mBannerMessage); break; /* ------------- VNSHWINFO -------------------- */ case VNSHWINFO: sr_handle_hwinfo(sr,(c_hwinfo*)buf); break; /* ---------------- VNS_RTABLE ---------------- */ case VNS_RTABLE: fprintf(stderr, "not yet setup to handle VNS_RTABLE message\n"); sr_close_instance(sr); if(buf) { free(buf); } return 0; break; /* ------------- VNS_AUTH_REQUEST ------------- */ case VNS_AUTH_REQUEST: if(!sr_handle_auth_request(sr, (c_auth_request*)buf)) ret = -1; break; /* ------------- VNS_AUTH_STATUS -------------- */ case VNS_AUTH_STATUS: if(!sr_handle_auth_status(sr, (c_auth_status*)buf)) ret = -1; break; default: printf("unknown command: %d\n", command); break; }/* -- switch -- */ if(buf) { free(buf); } return ret; }/* -- sr_read_from_server -- */