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