external_comm.c

来自「用于传感器网络的节点操作系统 TinyOS 结构设计非常有意思」· C语言 代码 · 共 540 行

C
540
字号
/*									tab:4 * * * "Copyright (c) 2000-2002 The Regents of the University  of California.   * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement is * hereby granted, provided that the above copyright notice, the following * two paragraphs and the author appear in all copies of this software. *  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." * *//*									tab:4 *  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.  By *  downloading, copying, installing or using the software you agree to *  this license.  If you do not agree to this license, do not download, *  install, copy or use the software. * *  Intel Open Source License  * *  Copyright (c) 2002 Intel Corporation  *  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. *	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. *      Neither the name of the Intel Corporation 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 COPYRIGHT HOLDERS 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 INTEL OR ITS *  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. *  *  *//* * * Authors:		Philip Levis <pal@cs.berkeley.edu> * * *//* *   FILE: external_comm.c * AUTHOR: pal *   DESC: Routines for communication with other processes. */#if __BYTE_ORDER == __BIG_ENDIAN#  define htonll(x) (x)#  define ntohll(x) (x)#else#  if __BYTE_ORDER == __LITTLE_ENDIAN#    define htonll(x) __bswap_64(x)#    define ntohll(x) __bswap_64(x)#  endif#endifconst short radioInPort  =    RADIO_IN_PORT; // Need this - should be a server socket -ri simulator blocks until client closes const short radioOutPort =    RADIO_OUT_PORT; // Need this -ro const short radioBitOutPort = RADIO_BIT_OUT_PORT; // Don't need thisconst short radioRTInPort =   RADIO_RT_IN_PORT; // Server socket // Need thisconst short radioRTOutPort =  RADIO_RT_OUT_PORT; const short uartInPort   =    UART_IN_PORT; // Don't need thisconst short uartOutPort  =    UART_OUT_PORT; // Don't need thisconst short loggingPort  =    LOGGING_PORT; //Server socket // Need thisconst short radioRawOutPort = RADIO_RAW_OUT_PORT; // Don't need this#define localAddr INADDR_LOOPBACKint inUARTFD        = -1;int outUARTFD       = -1;int inRadioFD       = -1;int outRadioFD      = -1;int outRadioBitFD   = -1;int inRTRadioFD     = -1;int outRTRadioFD    = -1;int outRTRadioServerFD = -1;int loggingFD       = -1;int loggingClientFD = -1;int rawOutRadioFD   = -1;pthread_t radioRTReadThread;pthread_t radioWriteThread;pthread_t loggingThread;pthread_mutex_t logFDLock;pthread_mutex_t rtWriteClientLock;pthread_cond_t rtWriteClientCond;int createSocket(short port);int createServerSocket(short port);int createServerSocketAndWait(short port);void* rtRadioRead(void* arg);void* rtConnectRadioWrite(void* arg);void* loggingAccept(void* arg);char injectedBitmask [] = {0x00, 0x00, 0x00, 0x00, 0x00};int loggingPause;int readInRadioMessages();// this method takes as input from MAIN.c radio_in_port and radio_out_port// for user specified port numbers void initializeSockets() {  //initializeIncomingUART();  //initializeOutgoingUART();  initializeIncomingRTRadio();  initializeOutgoingRTRadio();  //initializeOutgoingBitRadio();  //initializeOutgoingRawRadio();}int initializeIncomingUART() {  inUARTFD = createSocket(uartInPort);  if (inUARTFD >= 0) {    dbg_clear(DBG_SIM, "SIM: Incoming UART messages initialized at fd %i.\n", inUARTFD);  }  return 1;}int initializeOutgoingUART() {  outUARTFD = createSocket(uartOutPort);  if (outUARTFD >= 0) {    dbg_clear(DBG_SIM, "SIM: Outgoing UART messages initialized.\n");    return 1;  }  else {    return 0;  }}int initializeIncomingRadio(int radio_in_port) {  int portToUse = radioInPort;    if (radio_in_port != -1)     portToUse = radio_in_port;    inRadioFD = createServerSocketAndWait(portToUse);  if (inRadioFD >= 0) {    readInRadioMessages();    dbg_clear(DBG_SIM, "SIM: Incoming radio messages initialized at fd %i.\n", inRadioFD);    return 1;  }  else {    return 0;  }}// Need to change to server socket for after-start connection capability.int initializeIncomingRTRadio() {  char ftime[128];  dbg_clear(DBG_SIM, "SIM: Creating server socket for dynamic packet injection.\n");    inRTRadioFD = createServerSocket(radioRTInPort);  if (inRTRadioFD >= 0) {    pthread_create(&radioRTReadThread, NULL, rtRadioRead, &inRTRadioFD);    printTime(ftime,128);    dbg_clear(DBG_SIM, "SIM: Real-time incoming radio message reader thread spawned at %s.\n", ftime);    return 1;  }  else {    return 0;  }}int initializeOutgoingRTRadio() {    char ftime[128];    dbg_clear(DBG_SIM, "SIM: Creating server socket for dynamic Radio Output Connection.\n");        pthread_cond_init(&rtWriteClientCond,NULL);    outRTRadioServerFD = createServerSocket(radioRTOutPort);        if (outRTRadioServerFD >= 0) {	pthread_create(&radioWriteThread, NULL, rtConnectRadioWrite, &outRTRadioServerFD);	printTime(ftime,128);	dbg_clear(DBG_SIM, "SIM: Real-time outgoing radio message thread spawned at %s.\n", ftime);	return 1;    }    else {	return 0;    }}int initializeOutgoingRadio(int radio_out_port) {  int portToUse = radioOutPort;  if (radio_out_port != -1)    portToUse = radio_out_port;    outRadioFD = createServerSocketAndWait(portToUse);  if (outRadioFD >= 0) {    dbg_clear(DBG_SIM, "SIM: Outgoing radio messages initialized at fd %i.\n", outRadioFD);    return 1;  }  else {    return 0;  }}int initializeOutgoingRawRadio() {  rawOutRadioFD = createSocket(radioRawOutPort);  if (rawOutRadioFD >= 0) {    dbg_clear(DBG_SIM, "SIM: Outgoing raw radio messages initialized at fd %i.\n", rawOutRadioFD);    return 1;  }  else {    return 0;  }}int initializeOutgoingBitRadio() {  outRadioBitFD = createSocket(radioBitOutPort);  if (outRadioBitFD >= 0) {    dbg_clear(DBG_SIM, "SIM: Outgoing radio messages initialized at fd %i.\n", outRadioBitFD);    return 1;  }  else {    return 0;  }}int initializeInvocationLogging() {  loggingFD = createServerSocket(loggingPort);  if (inRTRadioFD >= 0) {    loggingAccept(&loggingFD);    //pthread_create(&loggingThread, NULL, loggingAccept, &loggingFD);    dbg_clear(DBG_SIM, "SIM: Invocation logger initialized at fd %i.\n", (int)loggingFD);    return 1;  }  else {    return 0;  }  loggingPause = 0;}int createServerSocketAndWait(short port) {  int sockfd;  int clilen;  int rval;  struct sockaddr_in serv_addr;  struct sockaddr_in cli_addr;    memset(&serv_addr, 0, sizeof(serv_addr));  serv_addr.sin_family = AF_INET;  serv_addr.sin_port = htons(port);  serv_addr.sin_addr.s_addr = htonl(localAddr);    sockfd = socket(AF_INET, SOCK_STREAM, 0);  if (sockfd < 0) {    dbg_clear(DBG_SIM|DBG_ERROR, "SIM: Could not create server socket: %s\n", strerror(errno));    return -1;  }    do {       rval = bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));      if (rval < 0) {	  dbg_clear(DBG_SIM|DBG_ERROR, "SIM: Could not bind server socket to port %i: %s\n", (int)port, strerror(errno));	  dbg_clear(DBG_SIM|DBG_ERROR, "SIM: Will retry in 10 seconds.\n");	  sleep(10);      }   } while (rval < 0);  listen(sockfd, 1);  dbg_clear(DBG_SIM, "SIM: Created server socket waiting for client connection on port %i.\n", (int)port);  clilen = sizeof(cli_addr);    sockfd = accept(sockfd, (struct sockaddr*)&cli_addr, &clilen);  dbg_clear(DBG_SIM, "SIM: Accepted client socket: FD %i\n", sockfd);  return sockfd;}int createServerSocket(short port) {  struct sockaddr_in sock;  int sfd;  int rval = -1;    memset(&sock, 0, sizeof(sock));  sock.sin_family = AF_INET;  sock.sin_port = htons(port);  sock.sin_addr.s_addr = htonl(localAddr);  sfd = socket(AF_INET, SOCK_STREAM, 0);  if (sfd < 0) {    dbg_clear(DBG_SIM|DBG_ERROR, "SIM: Could not create server socket: %s\n", strerror(errno));    return -1;  }  while(rval < 0) {    rval = bind(sfd, (struct sockaddr*)&sock, sizeof(sock));    if (rval < 0) {      dbg_clear(DBG_SIM|DBG_ERROR, "SIM: Could not bind server socket to port %i: %s\n", (int)port, strerror(errno));      dbg_clear(DBG_SIM|DBG_ERROR, "SIM: Will retry in 10 seconds.\n");      sleep(10);    }  }  listen(sfd, 1);  dbg_clear(DBG_SIM, "SIM: Created server socket listening on port %i.\n", (int)port);  return sfd;}int createSocket(short port) {  struct sockaddr_in sock;  int fd;  int rval;    memset(&sock, 0, sizeof(sock));  sock.sin_family = AF_INET;  sock.sin_port = htons(port);  sock.sin_addr.s_addr = htonl(localAddr);  fd = socket(AF_INET, SOCK_STREAM, 0);  if (fd < 0) {    dbg_clear(DBG_ERROR, "SIM: Could not create incoming socket to port %i. Error: %s \n", (int)port, strerror(errno));    return -1;  }  rval = connect(fd, (struct sockaddr*)&sock, sizeof(sock));  if (rval < 0) {    close(fd);    dbg_clear(DBG_SIM, "SIM: Could not initiate connection to port %i for messages.\n", (int)port);    return -1;  }  dbg_clear(DBG_SIM, "SIM: Socket to port %i initialized at fd %i.\n", (int)port, fd);    return fd;}int readInUARTMessages() {  return 1;}int writeOutUartByte(long long ftime, short moteID, char value) {  UartByteMsg msg;  if (outUARTFD >= 0) {    msg.time = htonll(ftime);    msg.moteID = htons(moteID);    msg.data = value;    write(outUARTFD, &msg, sizeof(msg));    return 1;  }  else {    return 0;  }}void* loggingAccept(void* arg) {  int valid;  struct sockaddr_in client;  int fd = *((int*)arg);  int size = sizeof(client);  valid = 0;  while (!valid) {    pthread_mutex_lock(&logFDLock);    loggingClientFD = accept(fd, (struct sockaddr*)&client, &size);    valid = (loggingClientFD >= 0)? 1:0;    pthread_mutex_unlock(&logFDLock);  }    return NULL;}void setLoggingPause(int fpause) {  loggingPause = fpause;}int notifyTaskPosted(char* task) {  if (loggingFD < 0 || NODE_NUM != 0) {return 0;}    if (loggingClientFD >= 0 && tos_state.current_node == 0) {    char buf[1024];    int len = sprintf(buf, "%lli %s\n", tos_state.tos_time, task);    //tos_state.tos_time++;        len = write(loggingClientFD, buf, len);    if (len <= 0) {      loggingClientFD = -1;      pthread_create(&loggingThread, NULL, loggingAccept, &loggingFD);    }    len = read(loggingClientFD, buf, 1);    if (len <= 0) {      loggingClientFD = -1;      pthread_create(&loggingThread, NULL, loggingAccept, &loggingFD);    }  }  else {    dbg(DBG_SIM, "Task posted: %s\n", task);  }  if (loggingPause > 0) {    //usleep(loggingPause);  }    return 0;}int notifyEventSignaled(char* event) {  if (loggingFD < 0 || NODE_NUM != 0) {return 0;}    if (loggingClientFD >= 0 && tos_state.current_node == 0) {    char buf[1024];    int len = sprintf(buf, "%lli %s\n", tos_state.tos_time, event);    //tos_state.tos_time++;        len = write(loggingClientFD, buf, len);    if (len <= 0) {      loggingClientFD = -1;      pthread_create(&loggingThread, NULL, loggingAccept, &loggingFD);    }    len = read(loggingClientFD, buf, 1);    if (len <= 0) {      loggingClientFD = -1;      pthread_create(&loggingThread, NULL, loggingAccept, &loggingFD);    }  }  else {    dbg(DBG_SIM, "Event signaled: %s\n", event);  }  if (loggingPause > 0) {    //usleep(loggingPause);  }     return 0;}int notifyCommandCalled(char* command) {  if (loggingFD < 0 || NODE_NUM != 0) {return 0;}    if (loggingClientFD >= 0 && tos_state.current_node == 0) {    char buf[1024];    int len = sprintf(buf, "%lli %s\n", tos_state.tos_time, command);    //tos_state.tos_time++;    len = write(loggingClientFD, buf, len);    if (len <= 0) {      loggingClientFD = -1;      pthread_create(&loggingThread, NULL, loggingAccept, &loggingFD);    }    len = read(loggingClientFD, buf, 1);    if (len <= 0) {      loggingClientFD = -1;      pthread_create(&loggingThread, NULL, loggingAccept, &loggingFD);    }  }  else {    dbg(DBG_SIM, "Command called: %s\n", command);	  }  if (loggingPause > 0) {    //usleep(loggingPause);  }  return 0;}int printOtherTime(char* buf, int len, long long int ftime) {  int hours;  int minutes;  int seconds;  int secondBillionths;    secondBillionths = (int)(ftime % (long long) 4000000);  seconds = (int)(ftime / (long long) 4000000);  minutes = seconds / 60;  hours = minutes / 60;  secondBillionths *= (long long) 25;  seconds %= 60;  minutes %= 60;    return snprintf(buf, len, "%i:%i:%i.%08i", hours, minutes, seconds, secondBillionths);}int printTime(char* buf, int len) {  return printOtherTime(buf, len, tos_state.tos_time);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?