Code Search for Developers
 
 
  

SwNet.c from EmStar at Krugle


Show SwNet.c syntax highlighted

/*
 *
 * Copyright (c) 2003 The Regents of the University of California.  All 
 * rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Neither the name of the University nor the names of its
 *   contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
 

/*
 * Copyright (c) 2001 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above
 *    copyright notice, this list of conditions and the following
 *    disclaimer in the documentation and/or other materials provided
 *    with the distribution.
 * 3. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgement:
 *       This product includes software developed by Networked &
 *       Embedded Systems Lab at UCLA
 * 4. Neither the name of the University nor that of the Laboratory
 *    may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * Author: Simon Han (simonhan@ee.ucla.edu)
 */   
#include "sensorware.h"

#define ETHER_RETRY_MAX 3 
#define SCRIPT_HEADER_SIZE (6 + 11 * 4)

typedef struct{
  SwMessage msg;  // current message
  u_int16_t next_fragment;
  u_int16_t seq;
  int allocated_size;
  int processed_size;
  int total_fragment;
} SwNeighbor;

static pthread_mutex_t neighborMutex;
static Tcl_HashTable neiTable;

static pthread_mutex_t sendMutex;
static int sendSeq = 0;

// following for communicating ack packet type between 
// packet receiving thread and packet sending thread (script)
static pthread_mutex_t netMutex = PTHREAD_MUTEX_INITIALIZER;
static u_int16_t netPacketType = MAC_MSG_NULL;
static pthread_cond_t netCond = PTHREAD_COND_INITIALIZER;

static u_int16_t swNetHandleMessage(SwMessage *msgp);
static u_int16_t swNetHandleAgent(SwMessage *msgp);
static u_int16_t swNetHandleMacData(SwNeighbor *nei, 
				    SwNetHeader *nethdrp);
static int swNetHandleMacFragment(SwNeighbor *nei, 
				  SwNetHeader *nethdrp);
// Add neighbor number n to neiTable
SwNeighbor* swNetAddNeighbor(int n){
  int createSucceed;
  Tcl_HashEntry *neiEntry;
  SwNeighbor *newNei;
  
  neiEntry = Tcl_CreateHashEntry(&neiTable, (char *)n, &createSucceed);
  if(!createSucceed){
    return (SwNeighbor*)Tcl_GetHashValue(neiEntry);
  }
  if((newNei = (SwNeighbor*)ckalloc(sizeof(SwNeighbor))) != NULL){
    newNei->msg.data = NULL;
    newNei->seq = 0;
    newNei->next_fragment = 0;
    Tcl_SetHashValue(neiEntry, newNei);
    return newNei;
  }
  return NULL;
}

// Remove neighbor number n from neiTable
int swNetRemoveNeighbor(int n){
  Tcl_HashEntry *neiEntry;
  SwNeighbor *delNei;

  if(n < 0 || n == TOPO_BROADCAST_ADDR) return -EINVAL;
  neiEntry = Tcl_FindHashEntry(&neiTable, (char*)n);
  if(neiEntry == NULL) {return -EINVAL;}
  delNei = (SwNeighbor*)Tcl_GetHashValue(neiEntry);
  ckfree((void*)delNei);
  Tcl_DeleteHashEntry(neiEntry);
  return 0;
}

int swNetRecv(int src, char *buf, size_t len){
  SwNetHeader *nethdrp = (SwNetHeader*)buf;
  SwNeighbor *nei;
  u_int16_t ackType = MAC_MSG_NULL;
  //SwAddress retBox = {0};

  DEBUG("type = %d\n", nethdrp->pkt_type);
  pthread_mutex_lock(&neighborMutex);
  nei = swNetAddNeighbor(src);
  if(nei == NULL) {
    pthread_mutex_unlock(&neighborMutex);
    return -EAGAIN;
  }

  if(nethdrp->pkt_type == MAC_MSG_SUCCEED ||
    nethdrp->pkt_type == MAC_MSG_FAILED || 
    nethdrp->pkt_type == MAC_MSG_TRYAGAIN){
    pthread_mutex_unlock(&neighborMutex);
    pthread_mutex_lock(&netMutex);
    netPacketType = nethdrp->pkt_type;
    pthread_cond_signal(&netCond);
    pthread_mutex_unlock(&netMutex);
    return 0;
  }

  if(nethdrp->pkt_type == MAC_MSG_ANNOUNCE){
    SwNetHeader pkt;
    pthread_mutex_unlock(&neighborMutex);
    swNetSendMac(src, &pkt, MAC_MSG_REPLY);
    //DEBUG("recv announce, sent announce\n");
    return 0;
  }
  if(nethdrp->pkt_type == MAC_MSG_DATA){
    ackType = swNetHandleMacData(nei, nethdrp);
  }
  pthread_mutex_unlock(&neighborMutex);
  if(ackType != MAC_MSG_NULL){
    SwNetHeader pkt;
    swNetSendMac(src, &pkt, ackType);
  }
  return 0;
}

/*
void *swNetThread(void *arg){
  char buffer[MAC_MTU];
  int src;
  int len;
  while(1){
    if((len = Topo_Dev_Read(&src, buffer, MAC_MTU)) > 0){
      swNetRecv(src, buffer, len);
    }
  }
}
*/

int swNetDoSendNet(int dst, SwNetPacketHead *headp, char *buf, 
	      size_t len, u_int16_t type){
  int processed_size;
  int total_fragment;
  int send_retry = 0;
  int ackVal = MAC_MSG_NULL;
  
#ifdef MEASURE_NET
  struct timeval t;
#endif

  pthread_mutex_lock(&sendMutex);
  while(send_retry < ETHER_RETRY_MAX){
    // remain unchanged during fragmentation
    headp->hdr.pkt_type = type;
    headp->hdr.seq = sendSeq++;
    total_fragment = 
      ((len + sizeof(SwMessageHdr)) / (MAC_MTU - FRAG_MORE_HDR_SIZE));
    // will be changed based on the context
    headp->hdr.fragment = 0;
    processed_size = 0;
  
    if(total_fragment > 0){
      SwNetPacketFrag *fragp = (SwNetPacketFrag*)headp;
      //DEBUG("larger than zero\n");
      // *** first fragment ***
      memcpy(headp->data, buf, MAC_MTU - FRAG_ONE_HDR_SIZE);
      headp->hdr.pkt_size = MAC_MTU;
      processed_size = (MAC_MTU - FRAG_ONE_HDR_SIZE);
      if(Topo_Dev_Send(dst, (unsigned char*)headp, headp->hdr.pkt_size)
	 != headp->hdr.pkt_size){ 
	goto dev_send_failed;
      } 
      //printNetHeader(pkt.hdr);
      (headp->hdr.fragment)++;
      // *** middle fragments *** 
      while(headp->hdr.fragment < total_fragment){
	memcpy(fragp->data, buf + processed_size, MAC_MTU - FRAG_MORE_HDR_SIZE);
	processed_size += (MAC_MTU - FRAG_MORE_HDR_SIZE);
	if(Topo_Dev_Send(dst, (unsigned char*)fragp, fragp->hdr.pkt_size)
	   != fragp->hdr.pkt_size){ 
	  goto dev_send_failed;
	}
	(fragp->hdr.fragment)++;
      }
      // *** last fragment ***
      fragp->hdr.pkt_size = FRAG_MORE_HDR_SIZE + len - processed_size;
      memcpy(fragp->data, buf + processed_size, len - processed_size);
      if(Topo_Dev_Send(dst, (unsigned char*)fragp, fragp->hdr.pkt_size)
	 != fragp->hdr.pkt_size){ 
	goto dev_send_failed;
      }
      //sprintf(result, "%d", return_val);
      //DEBUG("last packet content\n");
      //DEBUG("%s\n", pkt.mac_data.data);
    }
    else{
      //DEBUG("single packet\n");
      if(len > 0 && buf != NULL){
	memcpy(headp->data, buf, len);    
      }
      headp->hdr.pkt_size = len + FRAG_ONE_HDR_SIZE;
      if(Topo_Dev_Send(dst, (unsigned char*)headp, headp->hdr.pkt_size)
	 != headp->hdr.pkt_size){ 
	goto dev_send_failed;
      } 
      //sprintf(result, "%d", return_val);
    }
    
    if(type != MAC_MSG_DATA || dst == TOPO_BROADCAST_ADDR){
      // we are only interested in retransmitting real data packets
      ackVal = MAC_MSG_SUCCEED;
      break;
    }

    {
      // sleep and wait for ack
      // notice that we obtain lock while sleeping to avoid any 
      // networking packet transmission 
      // this way, ack should be more reliable
      struct timeval tv;
      struct timespec tsp;
      //int rc;
      gettimeofday(&tv, NULL);
      ackVal = MAC_MSG_NULL;
 
      tv.tv_usec += 2000 * (total_fragment + 1);
      while(tv.tv_usec > 1000000){
	tv.tv_usec -= 1000000;
	tv.tv_sec += 1;
      }
      tsp.tv_sec = tv.tv_sec;
      tsp.tv_nsec = tv.tv_usec * 1000;

#ifdef MEASURE_NET
      swMeasureCtime(&t);
#endif  
    
	  // Roy: Ugly Hack
	  break;
	  /*
	  pthread_mutex_lock(&netMutex);
      rc = pthread_cond_timedwait(&netCond, &netMutex, &tsp);
      if(rc == 0){
	// get the ack...
	ackVal = netPacketType;
	if(ackVal == MAC_MSG_SUCCEED || ackVal == MAC_MSG_FAILED){
	  pthread_mutex_unlock(&netMutex);
#ifdef MEASURE_NET
          swMeasurePrintTimeDiff(&t, "net");
#endif
	  break;
	}
      }
      pthread_mutex_unlock(&netMutex);
		*/
  	  }
    
    send_retry++;
  }
  //printf("retry = %d, ack = %d\n", send_retry, ackVal);

  pthread_mutex_unlock(&sendMutex);
  if(dst != TOPO_BROADCAST_ADDR){                               
    pthread_mutex_lock(&neighborMutex);                              
    swNetAddNeighbor(dst);                                           
    pthread_mutex_unlock(&neighborMutex);
  }
  if(ackVal != MAC_MSG_SUCCEED){
    return 0;
  }
  if(send_retry == ETHER_RETRY_MAX){
    pthread_mutex_lock(&neighborMutex);
    swNetRemoveNeighbor(dst); 
    pthread_mutex_unlock(&neighborMutex);
    return -EAGAIN;
  }
  return len;

 dev_send_failed:
  pthread_mutex_unlock(&sendMutex);                                
  pthread_mutex_lock(&neighborMutex);                              
  swNetRemoveNeighbor(dst);                                        
  pthread_mutex_unlock(&neighborMutex);                            
  return 0;      
}

int swNetSendMac(int dst, SwNetHeader *pktp, u_int16_t type){
  pthread_mutex_lock(&sendMutex);
  pktp->pkt_type = type;
  pktp->pkt_size = sizeof(SwNetHeader);
  pktp->seq = sendSeq++;
  pktp->fragment = 0;
  if(Topo_Dev_Send(dst, (unsigned char*)pktp, pktp->pkt_size)
     == pktp->pkt_size){
    pthread_mutex_unlock(&sendMutex);
    return sizeof(SwNetHeader);
  }
  pthread_mutex_unlock(&sendMutex);
  pthread_mutex_lock(&neighborMutex);                              
  swNetRemoveNeighbor(dst);                                        
  pthread_mutex_unlock(&neighborMutex);
  return 0;
}

int swNetSendNet(int dst, SwNetPacketHead *pktp, char *buf, 
	      size_t len, u_int16_t type){
  char *compBuf; 
  unsigned long compSize = len + len/100 + 12;
  int retVal;
  if(buf == NULL){
    return swNetDoSendNet(dst, pktp, buf, len, type);
  }
  if((compBuf = ckalloc(compSize)) == NULL){
    return 0;
  }
  
  if(compress(compBuf, &compSize, buf, len) != Z_OK){
    ckfree(compBuf);
    return 0;
  }
  
  /*
  memcpy(compBuf, buf, len);
  compSize = len;
  */
  DEBUG("compSize = %d, len = %d\n", compSize, len);
  pktp->msghdr.orig_size = 
   pktp->msghdr.size;
  pktp->msghdr.size = compSize;
  retVal = swNetDoSendNet(dst, pktp, compBuf, compSize, type);
  ckfree(compBuf);
  return retVal;
}

int Tcl_SwSend_Cmd(ClientData clientData, Tcl_Interp *interp, 
		   int argc, char *argv[]) {
  SwAgent *agent = pthread_getspecific(agent_key);
  int id = agent->mailbox.addr.node;
  int node = 0, user = 0, family = 0, instance = 0;
  //char result[255];
  int size = 0;
  SwAddress dst;
  char *buf;
  int header_size = 0;

  if((argc != 3) || 
    (sscanf(argv[1], "%d.%d.%d.%d", &node, &user, &family, &instance) != 4)){
    Tcl_SetResult(interp, "invalid address", TCL_VOLATILE);
    return TCL_ERROR;
  }
  // NOTE: sscanf need int, so we need this conversion!!!
  dst.node = node;
  dst.user = (unsigned char)user;
  dst.family = (unsigned char)family;
  dst.instance = (unsigned char)instance;

  size = strlen(argv[2]) + 1;
  buf = (char*)ckalloc(SCRIPT_HEADER_SIZE + size);
  if(buf == NULL){
    Tcl_SetIntResult(interp, -ENOMEM);
    return TCL_OK;
  }
  header_size = sprintf(buf, "packet %d.%d.%d.%d ", agent->mailbox.addr.node,
			agent->mailbox.addr.user, agent->mailbox.addr.family, 
			agent->mailbox.addr.instance);
  memcpy(buf + header_size, argv[2], size);
  size += header_size;

  if(node == id){
    // loop back
    SwMessage msg;
    swMailConstructMsgHdr(&(msg.hdr), NET_MSG_MSG, &dst, &(agent->mailbox.addr),
			  size);
    msg.data = buf;
    if(swMailSend(&msg) >= 0){
      Tcl_SetIntResult(interp, size - header_size - 1);
    }
    else{
      ckfree(buf);
      Tcl_SetIntResult(interp, -ENOMEM);
    }
  }
  else{
    // send to the network
    SwNetPacketHead pkt;
    int return_val;
    swMailConstructMsgHdr(&(pkt.msghdr), 
			  NET_MSG_MSG, &dst, &(agent->mailbox.addr),
			  size);

    return_val = swNetSendNet(node, &pkt, buf, size, MAC_MSG_DATA);
    //if(return_val > 0){
    //Tcl_SetIntResult(interp, return_val - header_size - 1);
    //}
    //else{
    Tcl_SetIntResult(interp, return_val);
    //}
    ckfree(buf);
  }
  return TCL_OK;
}

// neighbor query interface
int swNeighborQuery(Tcl_Interp *interp, int argc, char *argv[]) {
  int j = 0;
  char result[4096];
  Tcl_HashSearch s;
  Tcl_HashEntry *neiEntry;

  result[0] = '\0';
  pthread_mutex_lock(&neighborMutex);
  neiEntry = Tcl_FirstHashEntry(&neiTable, &s);
  while(neiEntry){
    j += sprintf(result + j, "%d ", (int)Tcl_GetHashKey(&neiTable, neiEntry));
    neiEntry = Tcl_NextHashEntry(&s);
  }
  pthread_mutex_unlock(&neighborMutex);
        
  Tcl_SetResult(interp, result, TCL_VOLATILE);
  return TCL_OK;
}

int swNeighborList(int *list, int list_size){
  Tcl_HashSearch s;
  Tcl_HashEntry *neiEntry;  
  int retVal = 0;

  pthread_mutex_lock(&neighborMutex);
  neiEntry = Tcl_FirstHashEntry(&neiTable, &s);
  while(neiEntry && retVal < list_size){
    list[retVal] = (int)Tcl_GetHashKey(&neiTable, neiEntry); 
    neiEntry = Tcl_NextHashEntry(&s);
    retVal++;
  } 
  pthread_mutex_unlock(&neighborMutex);
  return retVal;
}

void printNetHeader(SwNetHeader hdr){
  register int i = 0;
  DEBUG("*********** NetHeader **********\n");
  DEBUG("dst MAC: ");
  for(i = 0; i < 6; i++){
    DEBUG("%x ", hdr.ethdr.ether_dhost[i]);
  }
  DEBUG("\n");
  DEBUG("src MAC: ");
  for(i = 0; i < 6; i++){
    DEBUG("%x ", hdr.ethdr.ether_shost[i]);
  }
  DEBUG("\n");
  DEBUG("MAC type: %x\n", hdr.pkt_type);
  DEBUG("pkt size: %d\n", hdr.pkt_size);
  DEBUG("fragment: %d\n", hdr.fragment);
  DEBUG("seq: %d\n", hdr.seq);
  DEBUG("********************************\n");
}

int swNetInterest(Tcl_Interp *interp, int argc, char *argv[], 
		    void **dataPtr){
  *dataPtr = NULL;
  Tcl_AppendResult(interp, "wlan: interest interface not ready", NULL);
  return TCL_ERROR;
}
int swNetActivate(SwInterest *interest){
  return 0;
}
int swNetDeactivate(SwInterest *interest){
  return 0;
}
int swNetDispose(void *param){
  return 0;
}
static SwDeviceOp netOp = {
  interest: swNetInterest,
  activate: swNetActivate,
  deactivate: swNetDeactivate,
  dispose: swNetDispose,
  /* thread: swNetThread, */
};
static SwDeviceOp neiOp = {
  query: swNeighborQuery,
};


int swNetInit(){
  int id;
  SwNetHeader pkt;

  pthread_mutex_init(&neighborMutex, NULL);
  pthread_mutex_init(&sendMutex, NULL);
  Tcl_InitHashTable(&neiTable, TCL_ONE_WORD_KEYS);
  id = Topo_Init_Callback(swNetRecv);
 
  swNetSendMac(TOPO_BROADCAST_ADDR, &pkt, MAC_MSG_ANNOUNCE); 
  // register device operations
  swDeviceRegister("wlan", &netOp);
  swDeviceRegister("neighbor", &neiOp);
  return id;
}

int swNetInterestInit(Tcl_Interp *interp){
   // XXX hardcode for wlan interest
  {
    SwInterest *interest =  swAgentCreateInterest("packet");
    swInterestSetDev(interest, &netOp, NULL);
    
  }
  return TCL_OK;
}


static u_int16_t swNetHandleMacData(SwNeighbor *nei, 
				    SwNetHeader *nethdrp){
  u_int16_t ackType = MAC_MSG_NULL;
  if((nei->next_fragment != nethdrp->fragment) || 
     (nei->next_fragment != 0 && nei->seq != nethdrp->seq)){
    // packet lost!!!
    DEBUG("lost packet... %d %d\n", nei->next_fragment, nethdrp->fragment);
    if(nei->msg.data != NULL){
      ckfree(nei->msg.data);
      nei->msg.data = NULL;
      DEBUG("free space\n");
    }
    nei->next_fragment = 0;
    if(nethdrp->fragment != 0){
      // drop the fragment
      DEBUG("drop fragment\n");
      return MAC_MSG_NULL;
    }
  }
  
  // handle fragments 
  swNetHandleMacFragment(nei, nethdrp);
  
  if(nethdrp->fragment == nei->total_fragment){
    // decompression here
    unsigned long decompSize = nei->msg.hdr.orig_size;
    char *decompBuf = ckalloc(decompSize);
    if(decompBuf != NULL){
      if(uncompress(decompBuf, &decompSize, 
		    nei->msg.data, nei->msg.hdr.size) 
	 == Z_OK){
	/*
	  if(memcpy(decompBuf, neighborList[i].msg.data, decompSize)){
	*/  
	ckfree(nei->msg.data);
	nei->msg.data = decompBuf;
	nei->msg.hdr.size = decompSize;

	//retBox = nei->msg.hdr.src;
	//DEBUG("recv completed message\n");
	//printMessage(neighborList[i].msg);
	if(nei->msg.hdr.mtype == NET_MSG_MSG){
	  ackType = swNetHandleMessage(&(nei->msg));	    
	}
	else if(nei->msg.hdr.mtype == NET_MSG_AGENT){
	  ackType = swNetHandleAgent(&(nei->msg));
	}
      }
      else{
	ckfree(decompBuf);
	ckfree(nei->msg.data);
	ackType = MAC_MSG_FAILED;
      }
    }
    else{
      ckfree(nei->msg.data);
      ackType = MAC_MSG_FAILED;
    }
    nei->msg.data = NULL;
    nei->next_fragment = 0;
  }
  else{
    //DEBUG("got fragment %d\n", neighborList[i].next_fragment);
    (nei->next_fragment)++;
  }
  return ackType;
}

static int swNetHandleMacFragment(SwNeighbor *nei, 
				  SwNetHeader *nethdrp){
  if(nethdrp->fragment == 0){
    SwNetPacketHead *netpktp = (SwNetPacketHead*)nethdrp;
    SwMessageHdr *msghdrp = &(netpktp->msghdr);
    // new packet...
    assert(nei->msg.data == NULL);
    nei->msg.data = (u_int8_t *)ckalloc(msghdrp->size);
    nei->allocated_size = msghdrp->size;
    nei->msg.hdr = *msghdrp;
    nei->total_fragment = 
      ((msghdrp->size + sizeof(SwMessageHdr)) / (MAC_MTU - FRAG_MORE_HDR_SIZE));
    nei->seq = nethdrp->seq;
    assert(nei->allocated_size >= (nethdrp->pkt_size - FRAG_ONE_HDR_SIZE));
    memcpy(nei->msg.data, 
	   netpktp->data, 
	   nethdrp->pkt_size - FRAG_ONE_HDR_SIZE);
    nei->processed_size = nethdrp->pkt_size - FRAG_ONE_HDR_SIZE;
  }
  else{
    SwNetPacketFrag *netpktp = (SwNetPacketFrag*)nethdrp;
    assert(nei->msg.data != NULL);
    assert((nei->allocated_size - nei->processed_size)
	   >= (nethdrp->pkt_size - FRAG_MORE_HDR_SIZE));
    memcpy(nei->msg.data + nei->processed_size, 
	   netpktp->data, 
	   nethdrp->pkt_size - FRAG_MORE_HDR_SIZE);
    nei->processed_size += (nethdrp->pkt_size - FRAG_MORE_HDR_SIZE);
  }
  return 0;
}

static u_int16_t swNetHandleAgent(SwMessage *msgp){
  SwMessage *msgPtr = (SwMessage *)ckalloc(sizeof(SwMessage));
  pthread_t pid;
  int broadcasted = 0;
  u_int16_t ackType = MAC_MSG_NULL;

  if(msgPtr != NULL){
    *msgPtr = *msgp;
    if(msgPtr->hdr.dst.node == TOPO_BROADCAST_ADDR){
      broadcasted = 1;
    }
    
    if(swMailReserve(&(msgPtr->hdr.dst)) == 0){
      ackType = MAC_MSG_SUCCEED;
      // box does not exist
      if(pthread_create(&pid, &thread_attr, swAgentThread, msgPtr) != 0){
	fprintf(stderr, "unable to create thread\n");
	ckfree(msgPtr->data);
	ckfree((void*)msgPtr);
	ackType = MAC_MSG_FAILED;
      }
    }
    else{
      // box exist!!!
      ckfree(msgPtr->data);
      ckfree((void*)msgPtr);
      ackType = MAC_MSG_FAILED;
    }
  }
  else{
    ckfree(msgp->data);
    ackType = MAC_MSG_FAILED;
  } 
  if(!broadcasted){
    return ackType;
  }
  else{
    return MAC_MSG_NULL;
  }
}

static u_int16_t swNetHandleMessage(SwMessage *msgp){
  if(swMailSend(msgp) < 0){
    ckfree(msgp->data);
    return MAC_MSG_FAILED;
  }
  else{
    return MAC_MSG_SUCCEED;
  }
}











See more files for this project here

EmStar

EmStar is a software system for developing and deploying wireless sensor networks involving Linux-based platforms. As the wireless sensor network community has attempted to deploy more complex designs---large-scale, long-lived systems that need self-organization and adaptivity---a number of difficult software design issues have arisen. Advances in software design have not kept pace with the capabilities of hardware. This is because designing for an adaptive, efficient, and useful sensor network has turned out to be surprisingly complex and difficult. EmStar is a Linux-based software framework, whose goal is to dramatically reduce this complexity, enabling work to be shared and reused, and simplifying and speeding the design of new sensor network applications.

Project homepage: http://cvs.cens.ucla.edu/emstar/
Programming language(s): C,Shell Script
License: other

  dev/
    SwDevTool.c
    SwLocation.c
    SwMagSensor.c
    SwMote.c
    SwThermal.c
    SwTimer.c
    SwVideo.c
    amigo.c
    uart.c
  tcl/
    panic.c
    regexp.c
    tclAssem.c
    tclBasic.c
    tclCmdAH.c
    tclCmdIL.c
    tclCmdMZ.c
    tclCmdNP.c
    tclExpr.c
    tclGet.c
    tclHash.c
    tclParse.c
    tclProc.c
    tclUtil.c
    tclVar.c
    tclXdbg.c
    tclXgen.c
    tclalloc.c
    tinytcl.c
  SwAgent.c
  SwAmigo.c
  SwDevice.c
  SwDiffQ.c
  SwInterest.c
  SwMailbox.c
  SwMeasure.c
  SwNet.c
  SwShell.c
  SwTclTools.c
  cygwindummy.c
  sensorware.c
  sensorwareD.c
  sensorwareI.c
  topology.c