Main Page | Data Structures | File List | Data Fields | Globals | Related Pages

netio.c

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Copyright 2005 Daniel Ferullo                                             *
00003  *                                                                           *
00004  * Licensed under the Apache License, Version 2.0 (the "License");           *
00005  * you may not use this file except in compliance with the License.          *
00006  * You may obtain a copy of the License at                                   *
00007  *                                                                           *
00008  *    http://www.apache.org/licenses/LICENSE-2.0                             *
00009  *                                                                           *
00010  * Unless required by applicable law or agreed to in writing, software       *
00011  * distributed under the License is distributed on an "AS IS" BASIS,         *
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
00013  * See the License for the specific language governing permissions and       *
00014  * limitations under the License.                                            *
00015  *                                                                           *
00016  *****************************************************************************/
00017 
00018 /**
00019  * @file netio.c
00020  * @author Daniel Ferullo (ferullo@cmu.edu)
00021  *
00022  * @brief provides functions to read and write to sockets specific to
00023  *        the messages that should be sent for the communication protocol.
00024  */
00025 
00026 #include "netio.h"
00027 #include "netio_private.h"
00028 #include "berkeleyapi.h"
00029 #include <unistd.h>
00030 #include <stdlib.h>
00031 #include <string.h>
00032 #include "util.h"
00033 #include "debug.h"
00034 
00035 errorcode readMsg(sock_t sd, comm_type_t type, void* buf, int buf_len) {
00036 
00037         /* this function does not assume that the entire network message is
00038          * received at once.  it allows for piecemeal reception of a message */
00039 
00040         /* declare local variables */
00041         int bytes_read, prev_bytes_read=0, ret, large_buf_len;
00042         char *large_buf, *buf_p;
00043         comm_type_t received_type;
00044         /* need to more all others up here too... */
00045 
00046         /* error check arguments */
00047         CHECK_NOT_NEG(sd,ERROR_NEG_ARG_1);
00048         CHECK_NOT_NEG(buf_len, ERROR_NEG_ARG_4);
00049 
00050         /* do function */
00051 
00052         /* declare the buffer to receive data into */
00053         if (buf != NULL)
00054                 memset(buf,'\0',buf_len);
00055 
00056         /* create a buffer to store the entire message, then later
00057          * keep only the payload */
00058         if ( (large_buf = (char*)malloc(buf_len+COMM_HEADER_LEN))==NULL)
00059                 return ERROR_MALLOC_FAILED;
00060         memset(large_buf,0,buf_len+COMM_HEADER_LEN);
00061         large_buf_len = buf_len+COMM_HEADER_LEN;
00062 
00063         /* this pointer will move throught the buf in the loop below */
00064         buf_p = large_buf;
00065 
00066         /* read the next message loop incase only part of the message is
00067          * received in one call to read() (allow reassembly of the fragments)
00068          */
00069         while (1) {
00070                 if ((bytes_read=read(sd, buf_p,
00071                                         large_buf_len-prev_bytes_read))<0) {
00072                         safe_free(large_buf);
00073                         return ERROR_1;
00074                 }
00075                 if (bytes_read==0) {
00076                         safe_free(large_buf);
00077                         return ERROR_TCP_READ;
00078                 }
00079                 if (bytes_read+prev_bytes_read > COMM_MAX_LEN) {
00080                         DEBUG(DBG_ALL,"ALL:WARNING: POSSIBLE BUFFER OVERRUN\n");
00081                         safe_free(large_buf);
00082                         return ERROR_2;
00083                 }
00084                 if (bytes_read + prev_bytes_read < COMM_MIN_LEN ) {
00085                         /* the entire header wasn't even received... */
00086                         prev_bytes_read += bytes_read;
00087                         buf_p = buf_p + bytes_read; /* pointer arithmatic */
00088                         continue;
00089                 }
00090                 /* cast the second 4 bytes as a unsigned long and check if the
00091                  * length is ok see communication.h for explanation of why
00092                  * those 4 bytes should be checked */
00093                 if ((ret=checkMsgLen(large_buf,bytes_read+prev_bytes_read))<0){
00094                         /* entire message not received */
00095                         if (ret!=NOT_OK) {
00096                                 /* there is a problem beyond that the message
00097                                  * not entirely receieved */
00098                                  safe_free(large_buf);
00099                                 return ERROR_3;
00100                         }
00101                         /* wait for the rest of the message */
00102                         prev_bytes_read += bytes_read;
00103                         buf_p = buf_p + bytes_read; /* pointer arithmatic */
00104                         continue;
00105                 }
00106                 /* the entire message is receieved... */
00107                 break;
00108         }
00109 
00110         /* now copy out the payload, if a buffer was passed in */
00111         if (buf != NULL)
00112                 memcpy(buf,large_buf+COMM_HEADER_LEN,buf_len);
00113 
00114         /* make sure it is the correct type */
00115         memcpy(&received_type,large_buf,4);
00116 
00117         safe_free(large_buf);
00118 
00119         if (ntohl(received_type) != type)
00120                 return ERROR_4;
00121 
00122         return SUCCESS;
00123 }
00124 
00125 errorcode checkMsgLen(char *msg, int msg_len) {
00126 
00127         unsigned long len;
00128 
00129         CHECK_NOT_NEG(msg,ERROR_NULL_ARG_1);
00130         CHECK_NOT_NEG(msg_len,ERROR_NEG_ARG_2);
00131         if (msg_len < COMM_MIN_LEN)
00132                 return ERROR_1;
00133 
00134         /* now cast two header fields into long and unsigned long
00135          * (per communication protocol)*/
00136         memcpy(&len, msg+COMM_TYPE_LEN, COMM_LENGTH_LEN);
00137         len = ntohl(len);
00138 
00139         if (msg_len > COMM_MAX_LEN)
00140                 return ERROR_2; /* message is longer than permisable size */
00141         else if (len < (msg_len - COMM_HEADER_LEN))
00142                 return ERROR_3; /* length field says the message is smaller
00143                                  * than what was received */
00144 
00145         if (len > (msg_len - COMM_HEADER_LEN) )
00146                 return NOT_OK; /* the length field says the message is longer
00147                                 * than what was received */
00148 
00149         return OK;
00150 }
00151 
00152 errorcode sendMsg(sock_t sd, long type, void* payload, long payload_len) {
00153 
00154         char *buf;
00155         long tmp;
00156         unsigned long utmp;
00157         
00158         CHECK_NOT_NEG(sd,ERROR_NEG_ARG_1);
00159         CHECK_NOT_NEG(payload_len,ERROR_NEG_ARG_4);
00160         if ((payload==NULL)&&(payload_len!=0))
00161                 return ERROR_NULL_ARG_3;
00162 
00163         buf = (char*)malloc(COMM_HEADER_LEN+payload_len);
00164         if (buf==NULL)
00165                 return ERROR_MALLOC_FAILED;
00166 
00167         /* make a message and send it */
00168 
00169         /* add type */
00170         tmp = htonl(type);
00171         memcpy(buf, &tmp, COMM_TYPE_LEN);
00172 
00173         /* add length */
00174         utmp = htonl(payload_len);
00175         memcpy(buf+COMM_TYPE_LEN, &utmp, COMM_LENGTH_LEN);
00176 
00177         /* add payload */
00178         if (payload_len != 0)
00179                 memcpy(buf+COMM_TYPE_LEN+COMM_LENGTH_LEN,payload,payload_len);
00180 
00181         /* send the message */
00182         if( write(sd, buf, COMM_HEADER_LEN+payload_len) < 0 ) {
00183                 DEBUG(DBG_NETWORK,"NETWORK:Failed to send data to socket.\n");
00184                 safe_free(buf);
00185                 return ERROR_TCP_SEND;
00186         }
00187 
00188         safe_free(buf);
00189         return SUCCESS;
00190 }
00191 

Generated on Wed Mar 30 23:20:47 2005 for NATBLASTER by  doxygen 1.3.9.1