New file |
| | |
| | | /* ******************************************************************************** |
| | | * Copyright: (C) 2012 Guo Wenxue <guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_comport.c |
| | | * Description: It's the comport operate library. |
| | | * |
| | | * Version: 1.0.0(10/17/2011~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "10/17/2011 03:33:25 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include "cp_comport.h" |
| | | |
| | | /************************************************************************************** |
| | | * Description: Set the comport structure |
| | | * Input Args: dev_name: The comport device name path, such as '/dev/ttyS3' |
| | | * baudrate: The baudrate, such as 115200 |
| | | * settings: The databit,parity,stopbit,flowctrl settings, such as '8N1N' |
| | | * Output Args: NONE |
| | | * Return Value: The COM_PORT structure pointer. |
| | | *************************************************************************************/ |
| | | COM_PORT *comport_init(const char *dev_name, int baudrate, const char *settings) |
| | | { |
| | | COM_PORT *comport = NULL; |
| | | if (NULL == (comport = (COM_PORT *) malloc(sizeof(COM_PORT)))) |
| | | { |
| | | return NULL; |
| | | } |
| | | memset(comport, 0, sizeof(COM_PORT)); |
| | | comport->is_connted = 0; |
| | | comport->frag_size = 128; |
| | | |
| | | strncpy(comport->dev_name, dev_name, DEVNAME_LEN); |
| | | comport->baudrate = baudrate; |
| | | |
| | | set_settings(comport, settings); |
| | | #ifdef COM_DEBUG |
| | | disp_settings(comport); |
| | | #endif |
| | | |
| | | return comport; |
| | | } |
| | | |
| | | #ifdef COM_DEBUG |
| | | void disp_settings(COM_PORT * comport) |
| | | { |
| | | COM_PRINT("Device:\t\t\t\"%s\"\n", comport->dev_name); |
| | | COM_PRINT("Baudrate:\t\t%ld\n", comport->baudrate); |
| | | COM_PRINT("DataBit:\t\t\'%d\'\n", comport->databit); |
| | | switch (comport->parity) |
| | | { |
| | | case 0: |
| | | COM_PRINT("Parity:\t\t\t\'N\'\n"); |
| | | break; |
| | | case 1: |
| | | COM_PRINT("Parity:\t\t\t\'O\'\n"); |
| | | break; |
| | | case 2: |
| | | COM_PRINT("Parity:\t\t\t\'E\'\n"); |
| | | break; |
| | | case 3: |
| | | COM_PRINT("Parity:\t\t\t\'S\'\n"); |
| | | break; |
| | | } |
| | | COM_PRINT("StopBit:\t\t\'%ld\'\n", (long int)comport->stopbit); |
| | | switch (comport->flowctrl) |
| | | { |
| | | case 0: |
| | | COM_PRINT("FlowCtrl:\t\t\'N\'\n"); |
| | | break; |
| | | case 1: |
| | | COM_PRINT("FlowCtrl:\t\t\'S\'\n"); |
| | | break; |
| | | case 2: |
| | | COM_PRINT("FlowCtrl:\t\t\'H\'\n"); |
| | | break; |
| | | case 3: |
| | | COM_PRINT("FlowCtrl:\t\t\'B\'\n"); |
| | | break; |
| | | } |
| | | COM_PRINT("\n"); |
| | | return; |
| | | } |
| | | #endif |
| | | |
| | | /************************************************************************************** |
| | | * Description: Set the comport databit,parity,stopbit,flowctrl |
| | | * Input Args: comport: the COM_PORT pointer |
| | | * settings: The databit/parity/stopbit/flowctrl settings as like "8N1N" |
| | | * Output Args: NONE |
| | | * Return Value: NONE |
| | | *************************************************************************************/ |
| | | void set_settings(COM_PORT * comport, const char *settings) |
| | | { |
| | | if(NULL==settings || NULL==comport) |
| | | return ; |
| | | |
| | | switch (settings[0]) /* data bit */ |
| | | { |
| | | case '7': |
| | | comport->databit = 7; |
| | | break; |
| | | case '8': |
| | | default: |
| | | comport->databit = 8; |
| | | break; |
| | | } |
| | | |
| | | switch (settings[1]) /* parity */ |
| | | { |
| | | case 'O': |
| | | case 'o': |
| | | comport->parity = 1; |
| | | break; |
| | | case 'E': |
| | | case 'e': |
| | | comport->parity = 2; |
| | | break; |
| | | case 'S': |
| | | case 's': |
| | | comport->parity = 3; |
| | | break; |
| | | case 'N': |
| | | case 'n': |
| | | default: |
| | | comport->parity = 0; |
| | | break; |
| | | } |
| | | |
| | | switch (settings[2]) /* stop bit */ |
| | | { |
| | | case '0': |
| | | comport->stopbit = 0; |
| | | break; |
| | | case '1': |
| | | default: |
| | | comport->stopbit = 1; |
| | | break; |
| | | } |
| | | |
| | | switch (settings[3]) /* flow control */ |
| | | { |
| | | case 'S': |
| | | case 's': |
| | | comport->flowctrl = 1; |
| | | break; |
| | | case 'H': |
| | | case 'h': |
| | | comport->flowctrl = 2; |
| | | break; |
| | | case 'B': |
| | | case 'b': |
| | | comport->flowctrl = 3; |
| | | break; |
| | | case 'N': |
| | | case 'n': |
| | | default: |
| | | comport->flowctrl = 0; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | void comport_close(COM_PORT * comport) |
| | | { |
| | | if (0 != comport->fd) |
| | | { |
| | | COM_PRINT("Close device \"%s\"\n", comport->dev_name); |
| | | close(comport->fd); |
| | | } |
| | | comport->is_connted = 0x00; |
| | | comport->fd = -1; |
| | | } |
| | | |
| | | void comport_term(COM_PORT * comport) |
| | | { |
| | | if(NULL == comport) |
| | | return; |
| | | |
| | | if (0 != comport->fd) |
| | | { |
| | | comport_close(comport); |
| | | } |
| | | memset(comport, 0x00, sizeof(COM_PORT)); |
| | | free(comport); |
| | | comport = NULL; |
| | | |
| | | return; |
| | | } |
| | | |
| | | int comport_open(COM_PORT * comport) |
| | | { |
| | | int retval = -1; |
| | | struct termios old_cfg, new_cfg; |
| | | int old_flags; |
| | | long tmp; |
| | | |
| | | if(NULL==comport) |
| | | return -1; |
| | | |
| | | comport_close(comport); |
| | | |
| | | |
| | | /* Not a TTY device */ |
| | | if( !strstr(comport->dev_name, "tty")) |
| | | { |
| | | COM_PRINT("Open Not tty device \"%s\"\n", comport->dev_name); |
| | | comport->fd = open(comport->dev_name, O_RDWR); |
| | | retval = comport->fd<0 ? -2 : comport->fd; |
| | | goto CleanUp; |
| | | } |
| | | |
| | | comport->fd = open(comport->dev_name, O_RDWR | O_NOCTTY | O_NONBLOCK); |
| | | if (comport->fd < 0) |
| | | { |
| | | retval = -3; |
| | | goto CleanUp; |
| | | } |
| | | COM_PRINT("Open device \"%s\"\n", comport->dev_name); |
| | | |
| | | if ((-1 != (old_flags = fcntl(comport->fd, F_GETFL, 0))) |
| | | && (-1 != fcntl(comport->fd, F_SETFL, old_flags & ~O_NONBLOCK))) |
| | | { |
| | | // Flush input and output |
| | | if (-1 == tcflush(comport->fd, TCIOFLUSH)) |
| | | { |
| | | retval = -4; |
| | | goto CleanUp; |
| | | } |
| | | } |
| | | else // Failure |
| | | { |
| | | retval = -5; |
| | | goto CleanUp; |
| | | } |
| | | |
| | | if (0 != tcgetattr(comport->fd, &old_cfg)) |
| | | { |
| | | retval = -6; // Failed to get Com settings |
| | | goto CleanUp; |
| | | } |
| | | |
| | | memset(&new_cfg, 0, sizeof(new_cfg)); |
| | | |
| | | /*=====================================*/ |
| | | /* Configure comport */ |
| | | /*=====================================*/ |
| | | |
| | | new_cfg.c_cflag &= ~CSIZE; |
| | | new_cfg.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); |
| | | new_cfg.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); |
| | | new_cfg.c_oflag &= ~(OPOST); |
| | | |
| | | /* Set the data bit */ |
| | | switch (comport->databit) |
| | | { |
| | | case 0x07: |
| | | new_cfg.c_cflag |= CS7; |
| | | break; |
| | | case 0x06: |
| | | new_cfg.c_cflag |= CS6; |
| | | break; |
| | | case 0x05: |
| | | new_cfg.c_cflag |= CS5; |
| | | break; |
| | | default: |
| | | new_cfg.c_cflag |= CS8; |
| | | break; |
| | | } |
| | | |
| | | /* Set the parity */ |
| | | switch (comport->parity) |
| | | { |
| | | case 0x01: // Odd |
| | | new_cfg.c_cflag |= (PARENB | PARODD); |
| | | new_cfg.c_cflag |= (INPCK | ISTRIP); |
| | | break; |
| | | case 0x02: // Even |
| | | new_cfg.c_cflag |= PARENB; |
| | | new_cfg.c_cflag &= ~PARODD;; |
| | | new_cfg.c_cflag |= (INPCK | ISTRIP); |
| | | break; |
| | | case 0x03: |
| | | new_cfg.c_cflag &= ~PARENB; |
| | | new_cfg.c_cflag &= ~CSTOPB; |
| | | break; |
| | | default: |
| | | new_cfg.c_cflag &= ~PARENB; |
| | | } |
| | | |
| | | /* Set Stop bit */ |
| | | if (0x01 != comport->stopbit) |
| | | { |
| | | new_cfg.c_cflag |= CSTOPB; |
| | | } |
| | | else |
| | | { |
| | | new_cfg.c_cflag &= ~CSTOPB; |
| | | } |
| | | |
| | | /* Set flow control */ |
| | | switch (comport->flowctrl) |
| | | { |
| | | case 1: // Software control |
| | | case 3: |
| | | new_cfg.c_cflag &= ~(CRTSCTS); |
| | | new_cfg.c_iflag |= (IXON | IXOFF); |
| | | break; |
| | | case 2: // Hardware control |
| | | new_cfg.c_cflag |= CRTSCTS; // Also called CRTSCTS |
| | | new_cfg.c_iflag &= ~(IXON | IXOFF); |
| | | break; |
| | | default: // NONE |
| | | new_cfg.c_cflag &= ~(CRTSCTS); |
| | | new_cfg.c_iflag &= ~(IXON | IXOFF); |
| | | break; |
| | | } |
| | | |
| | | /* Set baudrate */ |
| | | switch (comport->baudrate) |
| | | { |
| | | case 115200: |
| | | tmp = B115200; |
| | | break; |
| | | case 57600: |
| | | tmp = B57600; |
| | | break; |
| | | case 38400: |
| | | tmp = B38400; |
| | | break; |
| | | case 19200: |
| | | tmp = B19200; |
| | | break; |
| | | case 9600: |
| | | tmp = B9600; |
| | | break; |
| | | case 4800: |
| | | tmp = B4800; |
| | | break; |
| | | case 2400: |
| | | tmp = B2400; |
| | | break; |
| | | case 1800: |
| | | tmp = B1800; |
| | | break; |
| | | case 1200: |
| | | tmp = B1200; |
| | | break; |
| | | case 600: |
| | | tmp = B600; |
| | | break; |
| | | case 300: |
| | | tmp = B300; |
| | | break; |
| | | case 200: |
| | | tmp = B200; |
| | | break; |
| | | case 150: |
| | | tmp = B150; |
| | | break; |
| | | case 134: |
| | | tmp = B134; |
| | | break; |
| | | case 110: |
| | | tmp = B110; |
| | | break; |
| | | case 75: |
| | | tmp = B75; |
| | | break; |
| | | case 50: |
| | | tmp = B50; |
| | | break; |
| | | default: |
| | | tmp = B115200; |
| | | } |
| | | cfsetispeed(&new_cfg, tmp); |
| | | cfsetispeed(&new_cfg, tmp); |
| | | |
| | | /* Set the Com port timeout settings */ |
| | | new_cfg.c_cc[VMIN] = 0; |
| | | new_cfg.c_cc[VTIME] = 0; |
| | | |
| | | tcflush(comport->fd, TCIFLUSH); |
| | | if (0 != tcsetattr(comport->fd, TCSANOW, &new_cfg)) |
| | | { |
| | | retval = -7; // Failed to set device com port settings |
| | | goto CleanUp; |
| | | } |
| | | |
| | | COM_PRINT("Connected device \"%s\".\n", comport->dev_name); |
| | | comport->is_connted = 0x01; |
| | | retval = comport->fd; |
| | | |
| | | CleanUp: |
| | | COM_PRINT("Open device \"%s\" %s.\n", comport->dev_name, retval>0 ? "successfully" : "failure"); |
| | | return retval; |
| | | } |
| | | |
| | | void nonblock() |
| | | { |
| | | struct termios ttystate; |
| | | |
| | | //get the terminal state |
| | | tcgetattr(STDIN_FILENO, &ttystate); |
| | | |
| | | //turn off canonical mode |
| | | ttystate.c_lflag &= ~ICANON; |
| | | //minimum of number input read. |
| | | ttystate.c_cc[VMIN] = 1; |
| | | |
| | | //set the terminal attributes. |
| | | tcsetattr(STDIN_FILENO, TCSANOW, &ttystate); |
| | | } |
| | | |
| | | int kbhit() |
| | | { |
| | | struct timeval tv; |
| | | fd_set fds; |
| | | tv.tv_sec = 0; |
| | | tv.tv_usec = 0; |
| | | FD_ZERO(&fds); |
| | | FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0 |
| | | select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv); |
| | | return FD_ISSET(STDIN_FILENO, &fds); |
| | | } |
| | | |
| | | int comport_recv(COM_PORT * comport, char *buf, int buf_size, unsigned long timeout) |
| | | { |
| | | int retval = 0; // Function return value |
| | | int iRet; |
| | | fd_set stReadFds, stExcpFds; |
| | | struct timeval stTime; |
| | | |
| | | if (NULL == buf || 0 >= buf_size) |
| | | { |
| | | COM_PRINT("%s() usage error.\n", __FUNCTION__); |
| | | retval = -1; |
| | | goto CleanUp; |
| | | } |
| | | |
| | | if (0x01 != comport->is_connted) |
| | | { |
| | | COM_PRINT("%s() comport not connected.\n", __FUNCTION__); |
| | | retval = -2; |
| | | goto CleanUp; |
| | | } |
| | | |
| | | //printf("bufsize=%d timeout=%lu\n", buf_size, timeout); |
| | | |
| | | FD_ZERO(&stReadFds); |
| | | FD_ZERO(&stExcpFds); |
| | | FD_SET(comport->fd, &stReadFds); |
| | | FD_SET(comport->fd, &stExcpFds); |
| | | |
| | | if (0xFFFFFFFF != timeout) |
| | | { |
| | | stTime.tv_sec = (time_t) (timeout / 1000); |
| | | stTime.tv_usec = (long)(1000 * (timeout % 1000)); |
| | | |
| | | iRet = select(comport->fd + 1, &stReadFds, 0, &stExcpFds, &stTime); |
| | | if (0 == iRet) |
| | | { |
| | | retval = 0; // No data in Com port buffer |
| | | goto CleanUp; |
| | | } |
| | | else if (0 < iRet) |
| | | { |
| | | if (0 != FD_ISSET(comport->fd, &stExcpFds)) |
| | | { |
| | | retval = -6; // Error during checking recv status |
| | | COM_PRINT("Error checking recv status.\n"); |
| | | goto CleanUp; |
| | | } |
| | | |
| | | if (0 == FD_ISSET(comport->fd, &stReadFds)) |
| | | { |
| | | retval = 0; // No incoming data |
| | | COM_PRINT("No incoming data.\n"); |
| | | goto CleanUp; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | if (EINTR == errno) |
| | | { |
| | | COM_PRINT("catch interrupt signal.\n"); |
| | | retval = 0; // Interrupted signal catched |
| | | } |
| | | else |
| | | { |
| | | COM_PRINT("Check recv status failure.\n"); |
| | | retval = -7; // Error during checking recv status |
| | | } |
| | | |
| | | goto CleanUp; |
| | | } |
| | | } |
| | | |
| | | usleep(10000); /* sleep for 10ms for data incoming */ |
| | | |
| | | // Get data from Com port |
| | | iRet = read(comport->fd, buf, buf_size); |
| | | if (0 > iRet) |
| | | { |
| | | if (EINTR == errno) |
| | | retval = 0; // Interrupted signal catched |
| | | else |
| | | retval = -3; // Failed to read Com port |
| | | |
| | | goto CleanUp; |
| | | } |
| | | |
| | | #if 0 |
| | | { |
| | | int i=0; |
| | | printf("Receive %d bytes data: \n", iRet); |
| | | for(i=0; i<iRet; i++) |
| | | { |
| | | printf("0x%02x ", buf[i]); |
| | | } |
| | | printf("\n"); |
| | | } |
| | | #endif |
| | | |
| | | retval = iRet; |
| | | |
| | | CleanUp: |
| | | return retval; |
| | | |
| | | } |
| | | |
| | | int comport_send(COM_PORT * comport, char *buf, int send_bytes) |
| | | { |
| | | char *ptr, *end; |
| | | int retval = 0; |
| | | int send = 0; |
| | | |
| | | if (NULL == buf || 0 >= send_bytes) |
| | | { |
| | | COM_PRINT("%s() Usage error.\n", __FUNCTION__); |
| | | retval = -1; |
| | | goto CleanUp; |
| | | } |
| | | |
| | | if (0x01 != comport->is_connted) // Comport not opened ? |
| | | { |
| | | retval = -3; |
| | | COM_PRINT("Serail not connected.\n"); |
| | | goto CleanUp; |
| | | } |
| | | |
| | | //printf("Send %s with %d bytes.\n", buf, send_bytes); |
| | | |
| | | // Large data, then slice them and send |
| | | if (comport->frag_size < send_bytes) |
| | | { |
| | | ptr = buf; |
| | | end = buf + send_bytes; |
| | | |
| | | do |
| | | { |
| | | // Large than frag_size |
| | | if (comport->frag_size < (end - ptr)) |
| | | { |
| | | send = write(comport->fd, ptr, comport->frag_size); |
| | | if (0 >= send || comport->frag_size != send) |
| | | { |
| | | retval = -4; |
| | | goto CleanUp; |
| | | } |
| | | ptr += comport->frag_size; |
| | | } |
| | | else // Less than frag_size, maybe last fragmention. |
| | | { |
| | | send = write(comport->fd, ptr, (end - ptr)); |
| | | if (0 >= send || (end - ptr) != send) |
| | | { |
| | | retval = -4; |
| | | goto CleanUp; |
| | | } |
| | | ptr += (end - ptr); |
| | | } |
| | | } |
| | | while (ptr < end); |
| | | } |
| | | else // The send data is not large than a fragmention. |
| | | { |
| | | send = write(comport->fd, buf, send_bytes); |
| | | if (0 >= send || send_bytes != send) |
| | | { |
| | | retval = -5; |
| | | goto CleanUp; |
| | | } |
| | | } |
| | | |
| | | CleanUp: |
| | | return retval; |
| | | } |
| | | |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue <guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_comport.h |
| | | * Description: This head file is for the common TTY/Serial port operator library |
| | | * |
| | | * Version: 1.0.0(10/17/2011~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "10/17/2011 03:33:25 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | #ifndef _CP_COMPORT_H |
| | | #define _CP_COMPORT_H |
| | | |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <unistd.h> |
| | | #include <string.h> |
| | | #include <getopt.h> |
| | | #include <fcntl.h> |
| | | #include <errno.h> |
| | | #include <termios.h> |
| | | #include <sys/stat.h> |
| | | #include <sys/wait.h> |
| | | #include <sys/types.h> |
| | | #include <sys/stat.h> |
| | | #include <sys/select.h> |
| | | |
| | | #define BUF_64 64 |
| | | |
| | | #ifndef DEVNAME_LEN |
| | | #define DEVNAME_LEN 64 |
| | | #endif |
| | | |
| | | //#define COM_DEBUG |
| | | #ifdef COM_DEBUG |
| | | #define COM_PRINT(format,args...) printf(format, ##args) |
| | | #else |
| | | #define COM_PRINT(format,args...) do{} while(0); |
| | | #endif |
| | | |
| | | //#define msleep(m) {struct timespec cSleep; cSleep.tv_sec = 0; cSleep.tv_nsec = m * 1000; nanosleep(&cSleep, 0);} |
| | | |
| | | typedef struct __COM_PORT |
| | | { |
| | | unsigned char databit, parity, stopbit, flowctrl, is_connted; |
| | | char dev_name[DEVNAME_LEN]; |
| | | unsigned char used; /* This comport used or not now */ |
| | | int fd; |
| | | int frag_size; |
| | | long baudrate; |
| | | } COM_PORT; |
| | | |
| | | COM_PORT *comport_init(const char *dev_name, int baudrate, const char *settings); |
| | | void comport_close(COM_PORT * comport); |
| | | int comport_open(COM_PORT * comport); |
| | | void comport_term(COM_PORT * comport); |
| | | int comport_recv(COM_PORT * comport, char *buf, int buf_size, unsigned long timeout); |
| | | int comport_send(COM_PORT * comport, char *buf, int send_bytes); |
| | | |
| | | void set_settings(COM_PORT * comport, const char *settings); |
| | | void disp_settings(COM_PORT * comport); |
| | | void nonblock(); |
| | | int kbhit(); |
| | | |
| | | #endif |
New file |
| | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @file cp_dictionary.c |
| | | @author N. Devillard |
| | | @brief Implements a dictionary for string variables. |
| | | |
| | | This module implements a simple dictionary object, i.e. a list |
| | | of string/string associations. This object is useful to store e.g. |
| | | informations retrieved from a configuration file (ini files). |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | |
| | | /*--------------------------------------------------------------------------- |
| | | Includes |
| | | ---------------------------------------------------------------------------*/ |
| | | #include "cp_dictionary.h" |
| | | |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <string.h> |
| | | #include <unistd.h> |
| | | |
| | | /** Maximum value size for integers and doubles. */ |
| | | #define MAXVALSZ 1024 |
| | | |
| | | /** Minimal allocated number of entries in a dictionary */ |
| | | #define DICTMINSZ 128 |
| | | |
| | | /** Invalid key token */ |
| | | #define DICT_INVALID_KEY ((char*)-1) |
| | | |
| | | /*--------------------------------------------------------------------------- |
| | | Private functions |
| | | ---------------------------------------------------------------------------*/ |
| | | |
| | | /* Doubles the allocated size associated to a pointer */ |
| | | /* 'size' is the current allocated size. */ |
| | | static void * mem_double(void * ptr, int size) |
| | | { |
| | | void * newptr ; |
| | | |
| | | newptr = calloc(2*size, 1); |
| | | if (newptr==NULL) { |
| | | return NULL ; |
| | | } |
| | | memcpy(newptr, ptr, size); |
| | | free(ptr); |
| | | return newptr ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Duplicate a string |
| | | @param s String to duplicate |
| | | @return Pointer to a newly allocated string, to be freed with free() |
| | | |
| | | This is a replacement for strdup(). This implementation is provided |
| | | for systems that do not have it. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | static char * xstrdup(const char * s) |
| | | { |
| | | char * t ; |
| | | if (!s) |
| | | return NULL ; |
| | | t = (char*)malloc(strlen(s)+1) ; |
| | | if (t) { |
| | | strcpy(t,s); |
| | | } |
| | | return t ; |
| | | } |
| | | |
| | | /*--------------------------------------------------------------------------- |
| | | Function codes |
| | | ---------------------------------------------------------------------------*/ |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Compute the hash key for a string. |
| | | @param key Character string to use for key. |
| | | @return 1 unsigned int on at least 32 bits. |
| | | |
| | | This hash function has been taken from an Article in Dr Dobbs Journal. |
| | | This is normally a collision-free function, distributing keys evenly. |
| | | The key is stored anyway in the struct so that collision can be avoided |
| | | by comparing the key itself in last resort. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | unsigned dictionary_hash(const char * key) |
| | | { |
| | | int len ; |
| | | unsigned hash ; |
| | | int i ; |
| | | |
| | | len = strlen(key); |
| | | for (hash=0, i=0 ; i<len ; i++) { |
| | | hash += (unsigned)key[i] ; |
| | | hash += (hash<<10); |
| | | hash ^= (hash>>6) ; |
| | | } |
| | | hash += (hash <<3); |
| | | hash ^= (hash >>11); |
| | | hash += (hash <<15); |
| | | return hash ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Create a new dictionary object. |
| | | @param size Optional initial size of the dictionary. |
| | | @return 1 newly allocated dictionary objet. |
| | | |
| | | This function allocates a new dictionary object of given size and returns |
| | | it. If you do not know in advance (roughly) the number of entries in the |
| | | dictionary, give size=0. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | dictionary * dictionary_new(int size) |
| | | { |
| | | dictionary * d ; |
| | | |
| | | /* If no size was specified, allocate space for DICTMINSZ */ |
| | | if (size<DICTMINSZ) size=DICTMINSZ ; |
| | | |
| | | if (!(d = (dictionary *)calloc(1, sizeof(dictionary)))) { |
| | | return NULL; |
| | | } |
| | | d->size = size ; |
| | | d->val = (char **)calloc(size, sizeof(char*)); |
| | | d->key = (char **)calloc(size, sizeof(char*)); |
| | | d->hash = (unsigned int *)calloc(size, sizeof(unsigned)); |
| | | return d ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Delete a dictionary object |
| | | @param d dictionary object to deallocate. |
| | | @return void |
| | | |
| | | Deallocate a dictionary object and all memory associated to it. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void dictionary_del(dictionary * d) |
| | | { |
| | | int i ; |
| | | |
| | | if (d==NULL) return ; |
| | | for (i=0 ; i<d->size ; i++) { |
| | | if (d->key[i]!=NULL) |
| | | free(d->key[i]); |
| | | if (d->val[i]!=NULL) |
| | | free(d->val[i]); |
| | | } |
| | | free(d->val); |
| | | free(d->key); |
| | | free(d->hash); |
| | | free(d); |
| | | return ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get a value from a dictionary. |
| | | @param d dictionary object to search. |
| | | @param key Key to look for in the dictionary. |
| | | @param def Default value to return if key not found. |
| | | @return 1 pointer to internally allocated character string. |
| | | |
| | | This function locates a key in a dictionary and returns a pointer to its |
| | | value, or the passed 'def' pointer if no such key can be found in |
| | | dictionary. The returned character pointer points to data internal to the |
| | | dictionary object, you should not try to free it or modify it. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | char * dictionary_get(dictionary * d, const char * key, char * def) |
| | | { |
| | | unsigned hash ; |
| | | int i ; |
| | | |
| | | hash = dictionary_hash(key); |
| | | for (i=0 ; i<d->size ; i++) { |
| | | if (d->key[i]==NULL) |
| | | continue ; |
| | | /* Compare hash */ |
| | | if (hash==d->hash[i]) { |
| | | /* Compare string, to avoid hash collisions */ |
| | | if (!strcmp(key, d->key[i])) { |
| | | return d->val[i] ; |
| | | } |
| | | } |
| | | } |
| | | return def ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Set a value in a dictionary. |
| | | @param d dictionary object to modify. |
| | | @param key Key to modify or add. |
| | | @param val Value to add. |
| | | @return int 0 if Ok, anything else otherwise |
| | | |
| | | If the given key is found in the dictionary, the associated value is |
| | | replaced by the provided one. If the key cannot be found in the |
| | | dictionary, it is added to it. |
| | | |
| | | It is Ok to provide a NULL value for val, but NULL values for the dictionary |
| | | or the key are considered as errors: the function will return immediately |
| | | in such a case. |
| | | |
| | | Notice that if you dictionary_set a variable to NULL, a call to |
| | | dictionary_get will return a NULL value: the variable will be found, and |
| | | its value (NULL) is returned. In other words, setting the variable |
| | | content to NULL is equivalent to deleting the variable from the |
| | | dictionary. It is not possible (in this implementation) to have a key in |
| | | the dictionary without value. |
| | | |
| | | This function returns non-zero in case of failure. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int dictionary_set(dictionary * d, const char * key, const char * val) |
| | | { |
| | | int i ; |
| | | unsigned hash ; |
| | | |
| | | if (d==NULL || key==NULL) return -1 ; |
| | | |
| | | /* Compute hash for this key */ |
| | | hash = dictionary_hash(key) ; |
| | | /* Find if value is already in dictionary */ |
| | | if (d->n>0) { |
| | | for (i=0 ; i<d->size ; i++) { |
| | | if (d->key[i]==NULL) |
| | | continue ; |
| | | if (hash==d->hash[i]) { /* Same hash value */ |
| | | if (!strcmp(key, d->key[i])) { /* Same key */ |
| | | /* Found a value: modify and return */ |
| | | if (d->val[i]!=NULL) |
| | | free(d->val[i]); |
| | | d->val[i] = val ? xstrdup(val) : NULL ; |
| | | /* Value has been modified: return */ |
| | | return 0 ; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | /* Add a new value */ |
| | | /* See if dictionary needs to grow */ |
| | | if (d->n==d->size) { |
| | | |
| | | /* Reached maximum size: reallocate dictionary */ |
| | | d->val = (char **)mem_double(d->val, d->size * sizeof(char*)) ; |
| | | d->key = (char **)mem_double(d->key, d->size * sizeof(char*)) ; |
| | | d->hash = (unsigned int *)mem_double(d->hash, d->size * sizeof(unsigned)) ; |
| | | if ((d->val==NULL) || (d->key==NULL) || (d->hash==NULL)) { |
| | | /* Cannot grow dictionary */ |
| | | return -1 ; |
| | | } |
| | | /* Double size */ |
| | | d->size *= 2 ; |
| | | } |
| | | |
| | | /* Insert key in the first empty slot. Start at d->n and wrap at |
| | | d->size. Because d->n < d->size this will necessarily |
| | | terminate. */ |
| | | for (i=d->n ; d->key[i] ; ) { |
| | | if(++i == d->size) i = 0; |
| | | } |
| | | /* Copy key */ |
| | | d->key[i] = xstrdup(key); |
| | | d->val[i] = val ? xstrdup(val) : NULL ; |
| | | d->hash[i] = hash; |
| | | d->n ++ ; |
| | | return 0 ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Delete a key in a dictionary |
| | | @param d dictionary object to modify. |
| | | @param key Key to remove. |
| | | @return void |
| | | |
| | | This function deletes a key in a dictionary. Nothing is done if the |
| | | key cannot be found. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void dictionary_unset(dictionary * d, const char * key) |
| | | { |
| | | unsigned hash ; |
| | | int i ; |
| | | |
| | | if (key == NULL) { |
| | | return; |
| | | } |
| | | |
| | | hash = dictionary_hash(key); |
| | | for (i=0 ; i<d->size ; i++) { |
| | | if (d->key[i]==NULL) |
| | | continue ; |
| | | /* Compare hash */ |
| | | if (hash==d->hash[i]) { |
| | | /* Compare string, to avoid hash collisions */ |
| | | if (!strcmp(key, d->key[i])) { |
| | | /* Found key */ |
| | | break ; |
| | | } |
| | | } |
| | | } |
| | | if (i>=d->size) |
| | | /* Key not found */ |
| | | return ; |
| | | |
| | | free(d->key[i]); |
| | | d->key[i] = NULL ; |
| | | if (d->val[i]!=NULL) { |
| | | free(d->val[i]); |
| | | d->val[i] = NULL ; |
| | | } |
| | | d->hash[i] = 0 ; |
| | | d->n -- ; |
| | | return ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Dump a dictionary to an opened file pointer. |
| | | @param d Dictionary to dump |
| | | @param f Opened file pointer. |
| | | @return void |
| | | |
| | | Dumps a dictionary onto an opened file pointer. Key pairs are printed out |
| | | as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as |
| | | output file pointers. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void dictionary_dump(dictionary * d, FILE * out) |
| | | { |
| | | int i ; |
| | | |
| | | if (d==NULL || out==NULL) return ; |
| | | if (d->n<1) { |
| | | fprintf(out, "empty dictionary\n"); |
| | | return ; |
| | | } |
| | | for (i=0 ; i<d->size ; i++) { |
| | | if (d->key[i]) { |
| | | fprintf(out, "%20s\t[%s]\n", |
| | | d->key[i], |
| | | d->val[i] ? d->val[i] : "UNDEF"); |
| | | } |
| | | } |
| | | return ; |
| | | } |
| | | |
| | | |
| | | /* Test code */ |
| | | #ifdef TESTDIC |
| | | #define NVALS 20000 |
| | | int main(int argc, char *argv[]) |
| | | { |
| | | dictionary * d ; |
| | | char * val ; |
| | | int i ; |
| | | char cval[90] ; |
| | | |
| | | /* Allocate dictionary */ |
| | | printf("allocating...\n"); |
| | | d = dictionary_new(0); |
| | | |
| | | /* Set values in dictionary */ |
| | | printf("setting %d values...\n", NVALS); |
| | | for (i=0 ; i<NVALS ; i++) { |
| | | sprintf(cval, "%04d", i); |
| | | dictionary_set(d, cval, "salut"); |
| | | } |
| | | printf("getting %d values...\n", NVALS); |
| | | for (i=0 ; i<NVALS ; i++) { |
| | | sprintf(cval, "%04d", i); |
| | | val = dictionary_get(d, cval, DICT_INVALID_KEY); |
| | | if (val==DICT_INVALID_KEY) { |
| | | printf("cannot get value for key [%s]\n", cval); |
| | | } |
| | | } |
| | | printf("unsetting %d values...\n", NVALS); |
| | | for (i=0 ; i<NVALS ; i++) { |
| | | sprintf(cval, "%04d", i); |
| | | dictionary_unset(d, cval); |
| | | } |
| | | if (d->n != 0) { |
| | | printf("error deleting values\n"); |
| | | } |
| | | printf("deallocating...\n"); |
| | | dictionary_del(d); |
| | | return 0 ; |
| | | } |
| | | #endif |
| | | /* vim: set ts=4 et sw=4 tw=75 */ |
New file |
| | |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @file cp_dictionary.h |
| | | @author N. Devillard |
| | | @brief Implements a dictionary for string variables. |
| | | |
| | | This module implements a simple dictionary object, i.e. a list |
| | | of string/string associations. This object is useful to store e.g. |
| | | informations retrieved from a configuration file (ini files). |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | |
| | | #ifndef _CP_DICTIONARY_H_ |
| | | #define _CP_DICTIONARY_H_ |
| | | |
| | | /*--------------------------------------------------------------------------- |
| | | Includes |
| | | ---------------------------------------------------------------------------*/ |
| | | |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <string.h> |
| | | #include <unistd.h> |
| | | |
| | | /*--------------------------------------------------------------------------- |
| | | New types |
| | | ---------------------------------------------------------------------------*/ |
| | | |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Dictionary object |
| | | |
| | | This object contains a list of string/string associations. Each |
| | | association is identified by a unique string key. Looking up values |
| | | in the dictionary is speeded up by the use of a (hopefully collision-free) |
| | | hash function. |
| | | */ |
| | | /*-------------------------------------------------------------------------*/ |
| | | typedef struct _dictionary_ { |
| | | int n ; /** Number of entries in dictionary */ |
| | | int size ; /** Storage size */ |
| | | char ** val ; /** List of string values */ |
| | | char ** key ; /** List of string keys */ |
| | | unsigned * hash ; /** List of hash values for keys */ |
| | | } dictionary ; |
| | | |
| | | |
| | | /*--------------------------------------------------------------------------- |
| | | Function prototypes |
| | | ---------------------------------------------------------------------------*/ |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Compute the hash key for a string. |
| | | @param key Character string to use for key. |
| | | @return 1 unsigned int on at least 32 bits. |
| | | |
| | | This hash function has been taken from an Article in Dr Dobbs Journal. |
| | | This is normally a collision-free function, distributing keys evenly. |
| | | The key is stored anyway in the struct so that collision can be avoided |
| | | by comparing the key itself in last resort. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | unsigned dictionary_hash(const char * key); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Create a new dictionary object. |
| | | @param size Optional initial size of the dictionary. |
| | | @return 1 newly allocated dictionary objet. |
| | | |
| | | This function allocates a new dictionary object of given size and returns |
| | | it. If you do not know in advance (roughly) the number of entries in the |
| | | dictionary, give size=0. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | dictionary * dictionary_new(int size); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Delete a dictionary object |
| | | @param d dictionary object to deallocate. |
| | | @return void |
| | | |
| | | Deallocate a dictionary object and all memory associated to it. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void dictionary_del(dictionary * vd); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get a value from a dictionary. |
| | | @param d dictionary object to search. |
| | | @param key Key to look for in the dictionary. |
| | | @param def Default value to return if key not found. |
| | | @return 1 pointer to internally allocated character string. |
| | | |
| | | This function locates a key in a dictionary and returns a pointer to its |
| | | value, or the passed 'def' pointer if no such key can be found in |
| | | dictionary. The returned character pointer points to data internal to the |
| | | dictionary object, you should not try to free it or modify it. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | char * dictionary_get(dictionary * d, const char * key, char * def); |
| | | |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Set a value in a dictionary. |
| | | @param d dictionary object to modify. |
| | | @param key Key to modify or add. |
| | | @param val Value to add. |
| | | @return int 0 if Ok, anything else otherwise |
| | | |
| | | If the given key is found in the dictionary, the associated value is |
| | | replaced by the provided one. If the key cannot be found in the |
| | | dictionary, it is added to it. |
| | | |
| | | It is Ok to provide a NULL value for val, but NULL values for the dictionary |
| | | or the key are considered as errors: the function will return immediately |
| | | in such a case. |
| | | |
| | | Notice that if you dictionary_set a variable to NULL, a call to |
| | | dictionary_get will return a NULL value: the variable will be found, and |
| | | its value (NULL) is returned. In other words, setting the variable |
| | | content to NULL is equivalent to deleting the variable from the |
| | | dictionary. It is not possible (in this implementation) to have a key in |
| | | the dictionary without value. |
| | | |
| | | This function returns non-zero in case of failure. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int dictionary_set(dictionary * vd, const char * key, const char * val); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Delete a key in a dictionary |
| | | @param d dictionary object to modify. |
| | | @param key Key to remove. |
| | | @return void |
| | | |
| | | This function deletes a key in a dictionary. Nothing is done if the |
| | | key cannot be found. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void dictionary_unset(dictionary * d, const char * key); |
| | | |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Dump a dictionary to an opened file pointer. |
| | | @param d Dictionary to dump |
| | | @param f Opened file pointer. |
| | | @return void |
| | | |
| | | Dumps a dictionary onto an opened file pointer. Key pairs are printed out |
| | | as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as |
| | | output file pointers. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void dictionary_dump(dictionary * d, FILE * out); |
| | | |
| | | #endif |
New file |
| | |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @file cp_iniparser.c |
| | | @author N. Devillard |
| | | @brief Parser for ini files. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | /*---------------------------- Includes ------------------------------------*/ |
| | | #include <ctype.h> |
| | | #include "cp_iniparser.h" |
| | | |
| | | /*---------------------------- Defines -------------------------------------*/ |
| | | #define ASCIILINESZ (1024) |
| | | #define INI_INVALID_KEY ((char*)-1) |
| | | |
| | | /*--------------------------------------------------------------------------- |
| | | Private to this module |
| | | ---------------------------------------------------------------------------*/ |
| | | /** |
| | | * This enum stores the status for each parsed line (internal use only). |
| | | */ |
| | | typedef enum _line_status_ { |
| | | LINE_UNPROCESSED, |
| | | LINE_ERROR, |
| | | LINE_EMPTY, |
| | | LINE_COMMENT, |
| | | LINE_SECTION, |
| | | LINE_VALUE |
| | | } line_status ; |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Convert a string to lowercase. |
| | | @param s String to convert. |
| | | @return ptr to statically allocated string. |
| | | |
| | | This function returns a pointer to a statically allocated string |
| | | containing a lowercased version of the input string. Do not free |
| | | or modify the returned string! Since the returned string is statically |
| | | allocated, it will be modified at each function call (not re-entrant). |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | static char * strlwc(const char * s) |
| | | { |
| | | static char l[ASCIILINESZ+1]; |
| | | int i ; |
| | | |
| | | if (s==NULL) return NULL ; |
| | | memset(l, 0, ASCIILINESZ+1); |
| | | i=0 ; |
| | | while (s[i] && i<ASCIILINESZ) { |
| | | l[i] = (char)tolower((int)s[i]); |
| | | i++ ; |
| | | } |
| | | l[ASCIILINESZ]=(char)0; |
| | | return l ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Remove blanks at the beginning and the end of a string. |
| | | @param s String to parse. |
| | | @return ptr to statically allocated string. |
| | | |
| | | This function returns a pointer to a statically allocated string, |
| | | which is identical to the input string, except that all blank |
| | | characters at the end and the beg. of the string have been removed. |
| | | Do not free or modify the returned string! Since the returned string |
| | | is statically allocated, it will be modified at each function call |
| | | (not re-entrant). |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | static char * strstrip(const char * s) |
| | | { |
| | | static char l[ASCIILINESZ+1]; |
| | | char * last ; |
| | | |
| | | if (s==NULL) return NULL ; |
| | | |
| | | while (isspace((int)*s) && *s) s++; |
| | | memset(l, 0, ASCIILINESZ+1); |
| | | strcpy(l, s); |
| | | last = l + strlen(l); |
| | | while (last > l) { |
| | | if (!isspace((int)*(last-1))) |
| | | break ; |
| | | last -- ; |
| | | } |
| | | *last = (char)0; |
| | | return (char*)l ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get number of sections in a dictionary |
| | | @param d Dictionary to examine |
| | | @return int Number of sections found in dictionary |
| | | |
| | | This function returns the number of sections found in a dictionary. |
| | | The test to recognize sections is done on the string stored in the |
| | | dictionary: a section name is given as "section" whereas a key is |
| | | stored as "section:key", thus the test looks for entries that do not |
| | | contain a colon. |
| | | |
| | | This clearly fails in the case a section name contains a colon, but |
| | | this should simply be avoided. |
| | | |
| | | This function returns -1 in case of error. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int iniparser_getnsec(dictionary * d) |
| | | { |
| | | int i ; |
| | | int nsec ; |
| | | |
| | | if (d==NULL) return -1 ; |
| | | nsec=0 ; |
| | | for (i=0 ; i<d->size ; i++) { |
| | | if (d->key[i]==NULL) |
| | | continue ; |
| | | if (strchr(d->key[i], ':')==NULL) { |
| | | nsec ++ ; |
| | | } |
| | | } |
| | | return nsec ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get name for section n in a dictionary. |
| | | @param d Dictionary to examine |
| | | @param n Section number (from 0 to nsec-1). |
| | | @return Pointer to char string |
| | | |
| | | This function locates the n-th section in a dictionary and returns |
| | | its name as a pointer to a string statically allocated inside the |
| | | dictionary. Do not free or modify the returned string! |
| | | |
| | | This function returns NULL in case of error. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | char * iniparser_getsecname(dictionary * d, int n) |
| | | { |
| | | int i ; |
| | | int foundsec ; |
| | | |
| | | if (d==NULL || n<0) return NULL ; |
| | | foundsec=0 ; |
| | | for (i=0 ; i<d->size ; i++) { |
| | | if (d->key[i]==NULL) |
| | | continue ; |
| | | if (strchr(d->key[i], ':')==NULL) { |
| | | foundsec++ ; |
| | | if (foundsec>n) |
| | | break ; |
| | | } |
| | | } |
| | | if (foundsec<=n) { |
| | | return NULL ; |
| | | } |
| | | return d->key[i] ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Dump a dictionary to an opened file pointer. |
| | | @param d Dictionary to dump. |
| | | @param f Opened file pointer to dump to. |
| | | @return void |
| | | |
| | | This function prints out the contents of a dictionary, one element by |
| | | line, onto the provided file pointer. It is OK to specify @c stderr |
| | | or @c stdout as output files. This function is meant for debugging |
| | | purposes mostly. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void iniparser_dump(dictionary * d, FILE * f) |
| | | { |
| | | int i ; |
| | | |
| | | if (d==NULL || f==NULL) return ; |
| | | for (i=0 ; i<d->size ; i++) { |
| | | if (d->key[i]==NULL) |
| | | continue ; |
| | | if (d->val[i]!=NULL) { |
| | | fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]); |
| | | } else { |
| | | fprintf(f, "[%s]=UNDEF\n", d->key[i]); |
| | | } |
| | | } |
| | | return ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Save a dictionary to a loadable ini file |
| | | @param d Dictionary to dump |
| | | @param f Opened file pointer to dump to |
| | | @return void |
| | | |
| | | This function dumps a given dictionary into a loadable ini file. |
| | | It is Ok to specify @c stderr or @c stdout as output files. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void iniparser_dump_ini(dictionary * d, FILE * f) |
| | | { |
| | | int i ; |
| | | int nsec ; |
| | | char * secname ; |
| | | |
| | | if (d==NULL || f==NULL) return ; |
| | | |
| | | nsec = iniparser_getnsec(d); |
| | | if (nsec<1) { |
| | | /* No section in file: dump all keys as they are */ |
| | | for (i=0 ; i<d->size ; i++) { |
| | | if (d->key[i]==NULL) |
| | | continue ; |
| | | fprintf(f, "%s = %s\n", d->key[i], d->val[i]); |
| | | } |
| | | return ; |
| | | } |
| | | for (i=0 ; i<nsec ; i++) { |
| | | secname = iniparser_getsecname(d, i) ; |
| | | iniparser_dumpsection_ini(d, secname, f) ; |
| | | } |
| | | fprintf(f, "\n"); |
| | | return ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Save a dictionary section to a loadable ini file |
| | | @param d Dictionary to dump |
| | | @param s Section name of dictionary to dump |
| | | @param f Opened file pointer to dump to |
| | | @return void |
| | | |
| | | This function dumps a given section of a given dictionary into a loadable ini |
| | | file. It is Ok to specify @c stderr or @c stdout as output files. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void iniparser_dumpsection_ini(dictionary * d, char * s, FILE * f) |
| | | { |
| | | int j ; |
| | | char keym[ASCIILINESZ+1]; |
| | | int seclen ; |
| | | |
| | | if (d==NULL || f==NULL) return ; |
| | | if (! iniparser_find_entry(d, s)) return ; |
| | | |
| | | seclen = (int)strlen(s); |
| | | fprintf(f, "\n[%s]\n", s); |
| | | sprintf(keym, "%s:", s); |
| | | for (j=0 ; j<d->size ; j++) { |
| | | if (d->key[j]==NULL) |
| | | continue ; |
| | | if (!strncmp(d->key[j], keym, seclen+1)) { |
| | | fprintf(f, |
| | | "%-30s = %s\n", |
| | | d->key[j]+seclen+1, |
| | | d->val[j] ? d->val[j] : ""); |
| | | } |
| | | } |
| | | fprintf(f, "\n"); |
| | | return ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get the number of keys in a section of a dictionary. |
| | | @param d Dictionary to examine |
| | | @param s Section name of dictionary to examine |
| | | @return Number of keys in section |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int iniparser_getsecnkeys(dictionary * d, char * s) |
| | | { |
| | | int seclen, nkeys ; |
| | | char keym[ASCIILINESZ+1]; |
| | | int j ; |
| | | |
| | | nkeys = 0; |
| | | |
| | | if (d==NULL) return nkeys; |
| | | if (! iniparser_find_entry(d, s)) return nkeys; |
| | | |
| | | seclen = (int)strlen(s); |
| | | sprintf(keym, "%s:", s); |
| | | |
| | | for (j=0 ; j<d->size ; j++) { |
| | | if (d->key[j]==NULL) |
| | | continue ; |
| | | if (!strncmp(d->key[j], keym, seclen+1)) |
| | | nkeys++; |
| | | } |
| | | |
| | | return nkeys; |
| | | |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get the number of keys in a section of a dictionary. |
| | | @param d Dictionary to examine |
| | | @param s Section name of dictionary to examine |
| | | @return pointer to statically allocated character strings |
| | | |
| | | This function queries a dictionary and finds all keys in a given section. |
| | | Each pointer in the returned char pointer-to-pointer is pointing to |
| | | a string allocated in the dictionary; do not free or modify them. |
| | | |
| | | This function returns NULL in case of error. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | char ** iniparser_getseckeys(dictionary * d, char * s) |
| | | { |
| | | |
| | | char **keys; |
| | | |
| | | int i, j ; |
| | | char keym[ASCIILINESZ+1]; |
| | | int seclen, nkeys ; |
| | | |
| | | keys = NULL; |
| | | |
| | | if (d==NULL) return keys; |
| | | if (! iniparser_find_entry(d, s)) return keys; |
| | | |
| | | nkeys = iniparser_getsecnkeys(d, s); |
| | | |
| | | keys = (char**) malloc(nkeys*sizeof(char*)); |
| | | |
| | | seclen = (int)strlen(s); |
| | | sprintf(keym, "%s:", s); |
| | | |
| | | i = 0; |
| | | |
| | | for (j=0 ; j<d->size ; j++) { |
| | | if (d->key[j]==NULL) |
| | | continue ; |
| | | if (!strncmp(d->key[j], keym, seclen+1)) { |
| | | keys[i] = d->key[j]; |
| | | i++; |
| | | } |
| | | } |
| | | |
| | | return keys; |
| | | |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get the string associated to a key |
| | | @param d Dictionary to search |
| | | @param key Key string to look for |
| | | @param def Default value to return if key not found. |
| | | @return pointer to statically allocated character string |
| | | |
| | | This function queries a dictionary for a key. A key as read from an |
| | | ini file is given as "section:key". If the key cannot be found, |
| | | the pointer passed as 'def' is returned. |
| | | The returned char pointer is pointing to a string allocated in |
| | | the dictionary, do not free or modify it. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | char * iniparser_getstring(dictionary * d, const char * key, char * def) |
| | | { |
| | | char * lc_key ; |
| | | char * sval ; |
| | | |
| | | if (d==NULL || key==NULL) |
| | | return def ; |
| | | |
| | | lc_key = strlwc(key); |
| | | sval = dictionary_get(d, lc_key, def); |
| | | return sval ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get the string associated to a key, convert to an int |
| | | @param d Dictionary to search |
| | | @param key Key string to look for |
| | | @param notfound Value to return in case of error |
| | | @return integer |
| | | |
| | | This function queries a dictionary for a key. A key as read from an |
| | | ini file is given as "section:key". If the key cannot be found, |
| | | the notfound value is returned. |
| | | |
| | | Supported values for integers include the usual C notation |
| | | so decimal, octal (starting with 0) and hexadecimal (starting with 0x) |
| | | are supported. Examples: |
| | | |
| | | "42" -> 42 |
| | | "042" -> 34 (octal -> decimal) |
| | | "0x42" -> 66 (hexa -> decimal) |
| | | |
| | | Warning: the conversion may overflow in various ways. Conversion is |
| | | totally outsourced to strtol(), see the associated man page for overflow |
| | | handling. |
| | | |
| | | Credits: Thanks to A. Becker for suggesting strtol() |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int iniparser_getint(dictionary * d, const char * key, int notfound) |
| | | { |
| | | char * str ; |
| | | |
| | | str = iniparser_getstring(d, key, INI_INVALID_KEY); |
| | | if (str==INI_INVALID_KEY) return notfound ; |
| | | return (int)strtol(str, NULL, 0); |
| | | } |
| | | |
| | | int iniparser_getlong(dictionary * d, const char * key, int notfound) |
| | | { |
| | | char * str ; |
| | | |
| | | str = iniparser_getstring(d, key, INI_INVALID_KEY); |
| | | if (str==INI_INVALID_KEY) return notfound ; |
| | | return strtol(str, NULL, 0); |
| | | } |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get the string associated to a key, convert to a double |
| | | @param d Dictionary to search |
| | | @param key Key string to look for |
| | | @param notfound Value to return in case of error |
| | | @return double |
| | | |
| | | This function queries a dictionary for a key. A key as read from an |
| | | ini file is given as "section:key". If the key cannot be found, |
| | | the notfound value is returned. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | double iniparser_getdouble(dictionary * d, const char * key, double notfound) |
| | | { |
| | | char * str ; |
| | | |
| | | str = iniparser_getstring(d, key, INI_INVALID_KEY); |
| | | if (str==INI_INVALID_KEY) return notfound ; |
| | | return atof(str); |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get the string associated to a key, convert to a boolean |
| | | @param d Dictionary to search |
| | | @param key Key string to look for |
| | | @param notfound Value to return in case of error |
| | | @return integer |
| | | |
| | | This function queries a dictionary for a key. A key as read from an |
| | | ini file is given as "section:key". If the key cannot be found, |
| | | the notfound value is returned. |
| | | |
| | | A true boolean is found if one of the following is matched: |
| | | |
| | | - A string starting with 'y' |
| | | - A string starting with 'Y' |
| | | - A string starting with 't' |
| | | - A string starting with 'T' |
| | | - A string starting with '1' |
| | | |
| | | A false boolean is found if one of the following is matched: |
| | | |
| | | - A string starting with 'n' |
| | | - A string starting with 'N' |
| | | - A string starting with 'f' |
| | | - A string starting with 'F' |
| | | - A string starting with '0' |
| | | |
| | | The notfound value returned if no boolean is identified, does not |
| | | necessarily have to be 0 or 1. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int iniparser_getboolean(dictionary * d, const char * key, int notfound) |
| | | { |
| | | char * c ; |
| | | int ret ; |
| | | |
| | | c = iniparser_getstring(d, key, INI_INVALID_KEY); |
| | | if (c==INI_INVALID_KEY) return notfound ; |
| | | if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') { |
| | | ret = 1 ; |
| | | } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') { |
| | | ret = 0 ; |
| | | } else { |
| | | ret = notfound ; |
| | | } |
| | | return ret; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Finds out if a given entry exists in a dictionary |
| | | @param ini Dictionary to search |
| | | @param entry Name of the entry to look for |
| | | @return integer 1 if entry exists, 0 otherwise |
| | | |
| | | Finds out if a given entry exists in the dictionary. Since sections |
| | | are stored as keys with NULL associated values, this is the only way |
| | | of querying for the presence of sections in a dictionary. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int iniparser_find_entry( |
| | | dictionary * ini, |
| | | const char * entry |
| | | ) |
| | | { |
| | | int found=0 ; |
| | | if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) { |
| | | found = 1 ; |
| | | } |
| | | return found ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Set an entry in a dictionary. |
| | | @param ini Dictionary to modify. |
| | | @param entry Entry to modify (entry name) |
| | | @param val New value to associate to the entry. |
| | | @return int 0 if Ok, -1 otherwise. |
| | | |
| | | If the given entry can be found in the dictionary, it is modified to |
| | | contain the provided value. If it cannot be found, -1 is returned. |
| | | It is Ok to set val to NULL. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int iniparser_set(dictionary * ini, const char * entry, const char * val) |
| | | { |
| | | return dictionary_set(ini, strlwc(entry), val) ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Delete an entry in a dictionary |
| | | @param ini Dictionary to modify |
| | | @param entry Entry to delete (entry name) |
| | | @return void |
| | | |
| | | If the given entry can be found, it is deleted from the dictionary. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void iniparser_unset(dictionary * ini, const char * entry) |
| | | { |
| | | dictionary_unset(ini, strlwc(entry)); |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Load a single line from an INI file |
| | | @param input_line Input line, may be concatenated multi-line input |
| | | @param section Output space to store section |
| | | @param key Output space to store key |
| | | @param value Output space to store value |
| | | @return line_status value |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | static line_status iniparser_line( |
| | | char * input_line, |
| | | char * section, |
| | | char * key, |
| | | char * value) |
| | | { |
| | | line_status sta ; |
| | | char line[ASCIILINESZ+1]; |
| | | static char left_line[ASCIILINESZ+1]; |
| | | int len, offset ; |
| | | |
| | | strcpy(line, strstrip(input_line)); |
| | | len = (int)strlen(line); |
| | | |
| | | sta = LINE_UNPROCESSED ; |
| | | if (len<1) { |
| | | /* Empty line */ |
| | | sta = LINE_EMPTY ; |
| | | memset(input_line, 0, len); |
| | | } else if (line[0]=='#' || line[0]==';') { |
| | | /* Comment line */ |
| | | sta = LINE_COMMENT ; |
| | | memset(input_line, 0, len); |
| | | } else if (line[0]=='[') { |
| | | /* Section name */ |
| | | sscanf(line, "[%[^]]", section); |
| | | strcpy(section, strstrip(section)); |
| | | strcpy(section, strlwc(section)); |
| | | |
| | | /* Left configure will go to next time to parser */ |
| | | offset = strlen(section) + 2; |
| | | strcpy( left_line, strstrip(&(line[offset])) ); |
| | | strcpy( left_line, strstrip(left_line)); |
| | | |
| | | if( strlen(left_line) > 0) |
| | | { |
| | | strcpy(input_line, left_line); |
| | | strcat(input_line, "\n"); |
| | | } |
| | | else |
| | | { |
| | | memset(input_line, 0, len); |
| | | } |
| | | sta = LINE_SECTION ; |
| | | } else if (sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2 |
| | | || sscanf (line, "%[^=] = '%[^\']'", key, value) == 2 |
| | | || sscanf (line, "%[^=] = %[^;#]", key, value) == 2) { |
| | | char *ptr = NULL; |
| | | |
| | | /* Usual key=value, with or without comments */ |
| | | strcpy(key, strstrip(key)); |
| | | strcpy(key, strlwc(key)); |
| | | strcpy(value, strstrip(value)); |
| | | /* |
| | | * sscanf cannot handle '' or "" as empty values |
| | | * this is done here |
| | | */ |
| | | if (!strncmp(value, "\"\"", 2) || (!strncmp(value, "''", 2)) ) { |
| | | value[0]=0 ; |
| | | } |
| | | |
| | | ptr = strchr(line, '='); |
| | | if('\''==*(ptr+1) || '\"'==*(ptr+1)) |
| | | { |
| | | offset = strlen(key)+strlen(value) + 1 + 2; /* Skip $key='$val' */ |
| | | } |
| | | else |
| | | { |
| | | offset = strlen(key)+strlen(value) + 1; /* Skip $key=$val */ |
| | | } |
| | | strcpy( left_line, strstrip(&(line[offset])) ); |
| | | |
| | | if( strlen(left_line) > 0) |
| | | { |
| | | strcpy(input_line, left_line); |
| | | strcat(input_line, "\n"); |
| | | } |
| | | else |
| | | { |
| | | memset(input_line, 0, len); |
| | | } |
| | | sta = LINE_VALUE ; |
| | | } else if (sscanf(line, "%[^=] = %[;#]", key, value)==2 |
| | | || sscanf(line, "%[^=] %[=]", key, value) == 2) { |
| | | /* |
| | | * Special cases: |
| | | * key= |
| | | * key=; |
| | | * key=# |
| | | */ |
| | | strcpy(key, strstrip(key)); |
| | | strcpy(key, strlwc(key)); |
| | | value[0]=0 ; |
| | | sta = LINE_VALUE ; |
| | | } else { |
| | | /* Generate syntax error */ |
| | | sta = LINE_ERROR ; |
| | | memset(input_line, 0, len); |
| | | } |
| | | return sta ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Parse an ini file and return an allocated dictionary object |
| | | @param ininame Name of the ini file to read. |
| | | @return Pointer to newly allocated dictionary |
| | | |
| | | This is the parser for ini files. This function is called, providing |
| | | the name of the file to be read. It returns a dictionary object that |
| | | should not be accessed directly, but through accessor functions |
| | | instead. |
| | | |
| | | The returned dictionary must be freed using iniparser_freedict(). |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | dictionary * iniparser_load(const char * ininame) |
| | | { |
| | | FILE * in ; |
| | | |
| | | char line [ASCIILINESZ+1] ; |
| | | char section [ASCIILINESZ+1] ; |
| | | char key [ASCIILINESZ+1] ; |
| | | char tmp [ASCIILINESZ+1] ; |
| | | char val [ASCIILINESZ+1] ; |
| | | |
| | | int last=0 ; |
| | | int len ; |
| | | int lineno=0 ; |
| | | int errs=0; |
| | | |
| | | dictionary * dict ; |
| | | |
| | | if ((in=fopen(ininame, "r"))==NULL) { |
| | | fprintf(stderr, "iniparser: cannot open %s\n", ininame); |
| | | return NULL ; |
| | | } |
| | | |
| | | dict = dictionary_new(0) ; |
| | | if (!dict) { |
| | | fclose(in); |
| | | return NULL ; |
| | | } |
| | | |
| | | memset(line, 0, ASCIILINESZ); |
| | | memset(section, 0, ASCIILINESZ); |
| | | memset(key, 0, ASCIILINESZ); |
| | | memset(val, 0, ASCIILINESZ); |
| | | last=0 ; |
| | | |
| | | while (fgets(line+last, ASCIILINESZ-last, in)!=NULL) { |
| | | lineno++ ; |
| | | CONTINUE_PARSER: |
| | | len = (int)strlen(line)-1; |
| | | if (len==0) |
| | | continue; |
| | | /* Safety check against buffer overflows */ |
| | | if (line[len]!='\n') { |
| | | fprintf(stderr, |
| | | "iniparser: input line too long in %s (%d)\n", |
| | | ininame, |
| | | lineno); |
| | | dictionary_del(dict); |
| | | fclose(in); |
| | | return NULL ; |
| | | } |
| | | /* Get rid of \n and spaces at end of line */ |
| | | while ((len>=0) && |
| | | ((line[len]=='\n') || (isspace(line[len])))) { |
| | | line[len]=0 ; |
| | | len-- ; |
| | | } |
| | | /* Detect multi-line */ |
| | | if (line[len]=='\\') { |
| | | /* Multi-line value */ |
| | | last=len ; |
| | | continue ; |
| | | } else { |
| | | last=0 ; |
| | | } |
| | | |
| | | switch ( iniparser_line(line, section, key, val) ) { |
| | | case LINE_EMPTY: |
| | | case LINE_COMMENT: |
| | | break ; |
| | | |
| | | case LINE_SECTION: |
| | | errs = dictionary_set(dict, section, NULL); |
| | | break ; |
| | | |
| | | case LINE_VALUE: |
| | | sprintf(tmp, "%s:%s", section, key); |
| | | errs = dictionary_set(dict, tmp, val) ; |
| | | break ; |
| | | |
| | | case LINE_ERROR: |
| | | fprintf(stderr, "iniparser: syntax error in %s (%d):\n", |
| | | ininame, |
| | | lineno); |
| | | fprintf(stderr, "-> %s\n", line); |
| | | errs++ ; |
| | | break; |
| | | |
| | | default: |
| | | break ; |
| | | } |
| | | |
| | | if( strlen(line) > 0) |
| | | { |
| | | goto CONTINUE_PARSER; |
| | | } |
| | | |
| | | memset(line, 0, ASCIILINESZ); |
| | | last=0; |
| | | if (errs<0) { |
| | | fprintf(stderr, "iniparser: memory allocation failure\n"); |
| | | break ; |
| | | } |
| | | } |
| | | if (errs) { |
| | | dictionary_del(dict); |
| | | dict = NULL ; |
| | | } |
| | | fclose(in); |
| | | return dict ; |
| | | } |
| | | |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Free all memory associated to an ini dictionary |
| | | @param d Dictionary to free |
| | | @return void |
| | | |
| | | Free all memory associated to an ini dictionary. |
| | | It is mandatory to call this function before the dictionary object |
| | | gets out of the current context. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void iniparser_freedict(dictionary * d) |
| | | { |
| | | dictionary_del(d); |
| | | } |
| | | |
| | | /* vim: set ts=4 et sw=4 tw=75 */ |
New file |
| | |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @file cp_iniparser.h |
| | | @author N. Devillard |
| | | @brief Parser for ini files. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | |
| | | #ifndef _CP_INIPARSER_H_ |
| | | #define _CP_INIPARSER_H_ |
| | | |
| | | /*--------------------------------------------------------------------------- |
| | | Includes |
| | | ---------------------------------------------------------------------------*/ |
| | | |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <string.h> |
| | | |
| | | /* |
| | | * The following #include is necessary on many Unixes but not Linux. |
| | | * It is not needed for Windows platforms. |
| | | * Uncomment it if needed. |
| | | */ |
| | | /* #include <unistd.h> */ |
| | | |
| | | #include "cp_dictionary.h" |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get number of sections in a dictionary |
| | | @param d Dictionary to examine |
| | | @return int Number of sections found in dictionary |
| | | |
| | | This function returns the number of sections found in a dictionary. |
| | | The test to recognize sections is done on the string stored in the |
| | | dictionary: a section name is given as "section" whereas a key is |
| | | stored as "section:key", thus the test looks for entries that do not |
| | | contain a colon. |
| | | |
| | | This clearly fails in the case a section name contains a colon, but |
| | | this should simply be avoided. |
| | | |
| | | This function returns -1 in case of error. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | |
| | | int iniparser_getnsec(dictionary * d); |
| | | |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get name for section n in a dictionary. |
| | | @param d Dictionary to examine |
| | | @param n Section number (from 0 to nsec-1). |
| | | @return Pointer to char string |
| | | |
| | | This function locates the n-th section in a dictionary and returns |
| | | its name as a pointer to a string statically allocated inside the |
| | | dictionary. Do not free or modify the returned string! |
| | | |
| | | This function returns NULL in case of error. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | |
| | | char * iniparser_getsecname(dictionary * d, int n); |
| | | |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Save a dictionary to a loadable ini file |
| | | @param d Dictionary to dump |
| | | @param f Opened file pointer to dump to |
| | | @return void |
| | | |
| | | This function dumps a given dictionary into a loadable ini file. |
| | | It is Ok to specify @c stderr or @c stdout as output files. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | |
| | | void iniparser_dump_ini(dictionary * d, FILE * f); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Save a dictionary section to a loadable ini file |
| | | @param d Dictionary to dump |
| | | @param s Section name of dictionary to dump |
| | | @param f Opened file pointer to dump to |
| | | @return void |
| | | |
| | | This function dumps a given section of a given dictionary into a loadable ini |
| | | file. It is Ok to specify @c stderr or @c stdout as output files. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | |
| | | void iniparser_dumpsection_ini(dictionary * d, char * s, FILE * f); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Dump a dictionary to an opened file pointer. |
| | | @param d Dictionary to dump. |
| | | @param f Opened file pointer to dump to. |
| | | @return void |
| | | |
| | | This function prints out the contents of a dictionary, one element by |
| | | line, onto the provided file pointer. It is OK to specify @c stderr |
| | | or @c stdout as output files. This function is meant for debugging |
| | | purposes mostly. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void iniparser_dump(dictionary * d, FILE * f); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get the number of keys in a section of a dictionary. |
| | | @param d Dictionary to examine |
| | | @param s Section name of dictionary to examine |
| | | @return Number of keys in section |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int iniparser_getsecnkeys(dictionary * d, char * s); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get the number of keys in a section of a dictionary. |
| | | @param d Dictionary to examine |
| | | @param s Section name of dictionary to examine |
| | | @return pointer to statically allocated character strings |
| | | |
| | | This function queries a dictionary and finds all keys in a given section. |
| | | Each pointer in the returned char pointer-to-pointer is pointing to |
| | | a string allocated in the dictionary; do not free or modify them. |
| | | |
| | | This function returns NULL in case of error. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | char ** iniparser_getseckeys(dictionary * d, char * s); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get the string associated to a key |
| | | @param d Dictionary to search |
| | | @param key Key string to look for |
| | | @param def Default value to return if key not found. |
| | | @return pointer to statically allocated character string |
| | | |
| | | This function queries a dictionary for a key. A key as read from an |
| | | ini file is given as "section:key". If the key cannot be found, |
| | | the pointer passed as 'def' is returned. |
| | | The returned char pointer is pointing to a string allocated in |
| | | the dictionary, do not free or modify it. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | char * iniparser_getstring(dictionary * d, const char * key, char * def); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get the string associated to a key, convert to an int |
| | | @param d Dictionary to search |
| | | @param key Key string to look for |
| | | @param notfound Value to return in case of error |
| | | @return integer |
| | | |
| | | This function queries a dictionary for a key. A key as read from an |
| | | ini file is given as "section:key". If the key cannot be found, |
| | | the notfound value is returned. |
| | | |
| | | Supported values for integers include the usual C notation |
| | | so decimal, octal (starting with 0) and hexadecimal (starting with 0x) |
| | | are supported. Examples: |
| | | |
| | | - "42" -> 42 |
| | | - "042" -> 34 (octal -> decimal) |
| | | - "0x42" -> 66 (hexa -> decimal) |
| | | |
| | | Warning: the conversion may overflow in various ways. Conversion is |
| | | totally outsourced to strtol(), see the associated man page for overflow |
| | | handling. |
| | | |
| | | Credits: Thanks to A. Becker for suggesting strtol() |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int iniparser_getint(dictionary * d, const char * key, int notfound); |
| | | int iniparser_getlong(dictionary * d, const char * key, int notfound); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get the string associated to a key, convert to a double |
| | | @param d Dictionary to search |
| | | @param key Key string to look for |
| | | @param notfound Value to return in case of error |
| | | @return double |
| | | |
| | | This function queries a dictionary for a key. A key as read from an |
| | | ini file is given as "section:key". If the key cannot be found, |
| | | the notfound value is returned. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | double iniparser_getdouble(dictionary * d, const char * key, double notfound); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get the string associated to a key, convert to a boolean |
| | | @param d Dictionary to search |
| | | @param key Key string to look for |
| | | @param notfound Value to return in case of error |
| | | @return integer |
| | | |
| | | This function queries a dictionary for a key. A key as read from an |
| | | ini file is given as "section:key". If the key cannot be found, |
| | | the notfound value is returned. |
| | | |
| | | A true boolean is found if one of the following is matched: |
| | | |
| | | - A string starting with 'y' |
| | | - A string starting with 'Y' |
| | | - A string starting with 't' |
| | | - A string starting with 'T' |
| | | - A string starting with '1' |
| | | |
| | | A false boolean is found if one of the following is matched: |
| | | |
| | | - A string starting with 'n' |
| | | - A string starting with 'N' |
| | | - A string starting with 'f' |
| | | - A string starting with 'F' |
| | | - A string starting with '0' |
| | | |
| | | The notfound value returned if no boolean is identified, does not |
| | | necessarily have to be 0 or 1. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int iniparser_getboolean(dictionary * d, const char * key, int notfound); |
| | | |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Set an entry in a dictionary. |
| | | @param ini Dictionary to modify. |
| | | @param entry Entry to modify (entry name) |
| | | @param val New value to associate to the entry. |
| | | @return int 0 if Ok, -1 otherwise. |
| | | |
| | | If the given entry can be found in the dictionary, it is modified to |
| | | contain the provided value. If it cannot be found, -1 is returned. |
| | | It is Ok to set val to NULL. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int iniparser_set(dictionary * ini, const char * entry, const char * val); |
| | | |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Delete an entry in a dictionary |
| | | @param ini Dictionary to modify |
| | | @param entry Entry to delete (entry name) |
| | | @return void |
| | | |
| | | If the given entry can be found, it is deleted from the dictionary. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void iniparser_unset(dictionary * ini, const char * entry); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Finds out if a given entry exists in a dictionary |
| | | @param ini Dictionary to search |
| | | @param entry Name of the entry to look for |
| | | @return integer 1 if entry exists, 0 otherwise |
| | | |
| | | Finds out if a given entry exists in the dictionary. Since sections |
| | | are stored as keys with NULL associated values, this is the only way |
| | | of querying for the presence of sections in a dictionary. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int iniparser_find_entry(dictionary * ini, const char * entry) ; |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Parse an ini file and return an allocated dictionary object |
| | | @param ininame Name of the ini file to read. |
| | | @return Pointer to newly allocated dictionary |
| | | |
| | | This is the parser for ini files. This function is called, providing |
| | | the name of the file to be read. It returns a dictionary object that |
| | | should not be accessed directly, but through accessor functions |
| | | instead. |
| | | |
| | | The returned dictionary must be freed using iniparser_freedict(). |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | dictionary * iniparser_load(const char * ininame); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Free all memory associated to an ini dictionary |
| | | @param d Dictionary to free |
| | | @return void |
| | | |
| | | Free all memory associated to an ini dictionary. |
| | | It is mandatory to call this function before the dictionary object |
| | | gets out of the current context. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void iniparser_freedict(dictionary * d); |
| | | |
| | | #endif |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue <guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_log.c |
| | | * Description: This file is the linux infrastructural logger system library |
| | | * |
| | | * Version: 1.0.0(08/08/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "08/08/2012 04:24:01 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include "cp_logger.h" |
| | | //#include "cp_common.h" |
| | | |
| | | #define PRECISE_TIME_FACTOR 1000 |
| | | |
| | | static unsigned long log_rollback_size = LOG_ROLLBACK_NONE; |
| | | |
| | | static cp_logger *logger = NULL; |
| | | |
| | | char *log_str[LOG_LEVEL_MAX + 1] = { "", "F", "E", "W", "N", "D", "I", "T", "M" }; |
| | | |
| | | static char *cp_time_format = DEFAULT_TIME_FORMAT; |
| | | |
| | | void cp_log_set_time_format(char *time_format) |
| | | { |
| | | cp_time_format = time_format; |
| | | } |
| | | |
| | | static void cp_log_default_signal_handler(int sig) |
| | | { |
| | | if(!logger) |
| | | return ; |
| | | |
| | | if (sig == SIGHUP) |
| | | { |
| | | signal(SIGHUP, cp_log_default_signal_handler); |
| | | log_fatal("SIGHUP received - reopenning log file [%s]", logger->file); |
| | | cp_log_reopen(); |
| | | } |
| | | } |
| | | |
| | | static void log_banner(char *prefix) |
| | | { |
| | | if(!logger) |
| | | return ; |
| | | |
| | | fprintf(logger->fp, "%s log \"%s\" on level [%s] size [%lu] KiB, log system version %s\n", |
| | | prefix, logger->file, log_str[logger->level], log_rollback_size / 1024, LOG_VERSION_STR); |
| | | #ifdef LOG_FILE_LINE |
| | | fprintf(logger->fp, " [Date] [Time] [Level] [PID/TID] [File/Line] [Content]\n"); |
| | | #else |
| | | fprintf(logger->fp, " [Date] [Time] [Level] [PID/TID] [Content]\n"); |
| | | #endif |
| | | fprintf(logger->fp, "-------------------------------------------------------------\n"); |
| | | } |
| | | |
| | | static void check_and_rollback(void) |
| | | { |
| | | if(!logger) |
| | | return ; |
| | | |
| | | if (log_rollback_size != LOG_ROLLBACK_NONE) |
| | | { |
| | | long _curOffset = ftell(logger->fp); |
| | | |
| | | if ((_curOffset != -1) && (_curOffset >= log_rollback_size)) |
| | | { |
| | | char cmd[512]; |
| | | |
| | | snprintf(cmd, sizeof(cmd), "cp -f %s %s.roll", logger->file, logger->file); |
| | | system(cmd); |
| | | |
| | | if (-1 == fseek(logger->fp, 0L, SEEK_SET)) |
| | | fprintf(logger->fp, "log rollback fseek failed \n"); |
| | | |
| | | rewind(logger->fp); |
| | | |
| | | truncate(logger->file, 0); |
| | | log_banner("Already rollback"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | cp_logger *cp_log_init(cp_logger *log, char *filename, int level, int log_size) |
| | | { |
| | | if(NULL == log) |
| | | { |
| | | logger = malloc(sizeof(cp_logger)); |
| | | memset(logger, 0, sizeof(cp_logger)); |
| | | logger->flag |= CP_LOGGER_MALLOC; |
| | | } |
| | | else |
| | | { |
| | | logger = log; |
| | | logger->flag |= CP_LOGGER_ARGUMENT; |
| | | } |
| | | |
| | | if(NULL == logger) |
| | | { |
| | | return NULL; |
| | | } |
| | | |
| | | strncpy(logger->file, filename, FILENAME_LEN); |
| | | logger->level = level; |
| | | logger->size = log_size; |
| | | |
| | | return logger; |
| | | } |
| | | |
| | | int cp_log_open(void) |
| | | { |
| | | struct sigaction act; |
| | | char *filemode; |
| | | |
| | | if(!logger) |
| | | { |
| | | return -1; |
| | | } |
| | | |
| | | log_rollback_size = logger->size <= 0 ? LOG_ROLLBACK_NONE : logger->size*1024; /* Unit KiB */ |
| | | |
| | | if ('\0' == logger->file) |
| | | return -1; |
| | | |
| | | if (!strcmp(logger->file, DBG_LOG_FILE)) |
| | | { |
| | | logger->fp = stderr; |
| | | log_rollback_size = LOG_ROLLBACK_NONE; |
| | | logger->flag |= CP_LOGGER_CONSOLE; |
| | | goto OUT; |
| | | } |
| | | |
| | | filemode = (log_rollback_size==LOG_ROLLBACK_NONE) ? "a+" : "w+"; |
| | | |
| | | logger->fp = fopen(logger->file, filemode); |
| | | if (NULL == logger->fp) |
| | | { |
| | | fprintf(stderr, "Open log file \"%s\" in %s failure\n", logger->file, filemode); |
| | | return -2; |
| | | } |
| | | |
| | | act.sa_handler = cp_log_default_signal_handler; |
| | | sigemptyset(&act.sa_mask); |
| | | act.sa_flags = 0; |
| | | sigaction(SIGHUP, &act, NULL); |
| | | |
| | | OUT: |
| | | log_banner("Initialize"); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | void cp_log_close(void) |
| | | { |
| | | if (!logger || !logger->fp ) |
| | | return; |
| | | |
| | | log_banner("\nTerminate"); |
| | | cp_log_raw("\n\n\n\n"); |
| | | |
| | | fflush(logger->fp); |
| | | |
| | | fclose(logger->fp); |
| | | logger->fp = NULL; |
| | | |
| | | return ; |
| | | } |
| | | |
| | | int cp_log_reopen(void) |
| | | { |
| | | int rc = 0; |
| | | char *filemode; |
| | | |
| | | if( !logger ) |
| | | return -1; |
| | | |
| | | log_rollback_size = logger->size <= 0 ? LOG_ROLLBACK_NONE : logger->size*1024; /* Unit KiB */ |
| | | |
| | | if (logger->flag & CP_LOGGER_CONSOLE ) |
| | | { |
| | | fflush(logger->fp); |
| | | logger->fp = stderr; |
| | | return 0; |
| | | } |
| | | |
| | | if (logger->fp) |
| | | { |
| | | cp_log_close(); |
| | | filemode = log_rollback_size==LOG_ROLLBACK_NONE ? "a+" : "w+"; |
| | | logger->fp = fopen(logger->file, filemode); |
| | | |
| | | if (logger->fp == NULL) |
| | | rc = -2; |
| | | } |
| | | else |
| | | { |
| | | rc = -3; |
| | | } |
| | | |
| | | if (!rc) |
| | | { |
| | | log_banner("\nReopen"); |
| | | } |
| | | return rc; |
| | | } |
| | | |
| | | void cp_log_term(void) |
| | | { |
| | | if(!logger) |
| | | return ; |
| | | |
| | | cp_log_close(); |
| | | |
| | | if (logger->flag & CP_LOGGER_MALLOC ) |
| | | { |
| | | free(logger); |
| | | } |
| | | logger = NULL; |
| | | } |
| | | |
| | | void cp_log_raw(const char *fmt, ...) |
| | | { |
| | | va_list argp; |
| | | |
| | | if (!logger || !logger->fp) |
| | | return; |
| | | |
| | | check_and_rollback(); |
| | | |
| | | va_start(argp, fmt); |
| | | vfprintf(logger->fp, fmt, argp); |
| | | va_end(argp); |
| | | } |
| | | |
| | | static void cp_printout(char *level, char *fmt, va_list argp) |
| | | { |
| | | char buf[MAX_LOG_MESSAGE_LEN]; |
| | | struct tm *local; |
| | | struct timeval now; |
| | | char timestr[256]; |
| | | |
| | | if(!logger) |
| | | return ; |
| | | |
| | | pthread_t tid; |
| | | |
| | | check_and_rollback(); |
| | | |
| | | #ifdef MULTHREADS |
| | | tid = pthread_self(); |
| | | #else |
| | | tid = getpid(); |
| | | #endif |
| | | |
| | | gettimeofday(&now, NULL); |
| | | local = localtime(&now.tv_sec); |
| | | |
| | | strftime(timestr, 256, cp_time_format, local); |
| | | vsnprintf(buf, MAX_LOG_MESSAGE_LEN, fmt, argp); |
| | | |
| | | #ifdef DUMPLICATE_OUTPUT |
| | | printf("%s.%03ld [%s] [%06lu]: %s", |
| | | timestr, now.tv_usec / PRECISE_TIME_FACTOR, level, tid, buf); |
| | | #endif |
| | | |
| | | if (logger->fp) |
| | | fprintf(logger->fp, "%s.%03ld [%s] [%06lu]: %s", timestr, now.tv_usec / PRECISE_TIME_FACTOR, |
| | | level, tid, buf); |
| | | |
| | | if (logger->fp) |
| | | fflush(logger->fp); |
| | | } |
| | | |
| | | static void cp_printout_line(char *level, char *fmt, char *file, int line, va_list argp) |
| | | { |
| | | char buf[MAX_LOG_MESSAGE_LEN]; |
| | | struct tm *local; |
| | | struct timeval now; |
| | | char timestr[256]; |
| | | |
| | | if(!logger) |
| | | return ; |
| | | |
| | | pthread_t tid; |
| | | |
| | | check_and_rollback(); |
| | | |
| | | #ifdef MULTHREADS |
| | | tid = pthread_self(); |
| | | #else |
| | | tid = getpid(); |
| | | #endif |
| | | |
| | | gettimeofday(&now, NULL); |
| | | local = localtime(&now.tv_sec); |
| | | |
| | | strftime(timestr, 256, cp_time_format, local); |
| | | vsnprintf(buf, MAX_LOG_MESSAGE_LEN, fmt, argp); |
| | | |
| | | #ifdef DUMPLICATE_OUTPUT |
| | | printf("%s.%03ld [%s] [%06lu] (%s [%04d]) : %s", |
| | | timestr, now.tv_usec / PRECISE_TIME_FACTOR, level, tid, file, line, buf); |
| | | #endif |
| | | |
| | | if (logger->fp) |
| | | fprintf(logger->fp, "%s.%03ld [%s] [%06lu] (%s [%04d]) : %s", |
| | | timestr, now.tv_usec / PRECISE_TIME_FACTOR, level, tid, file, line, buf); |
| | | |
| | | if (logger->fp) |
| | | fflush(logger->fp); |
| | | } |
| | | |
| | | void cp_log_str(int level, const char *msg) |
| | | { |
| | | if (!logger || level>logger->level) |
| | | return; |
| | | |
| | | check_and_rollback(); |
| | | |
| | | if (logger->fp) |
| | | fwrite(msg, 1, strlen(msg), logger->fp); |
| | | |
| | | if(logger->fp) |
| | | fflush(logger->fp); |
| | | } |
| | | |
| | | void cp_log(int level, char *fmt, ...) |
| | | { |
| | | va_list argp; |
| | | |
| | | if (!logger || level>logger->level) |
| | | return; |
| | | |
| | | va_start(argp, fmt); |
| | | cp_printout(log_str[level], fmt, argp); |
| | | va_end(argp); |
| | | } |
| | | |
| | | void cp_log_line(int level, char *file, int line, char *fmt, ...) |
| | | { |
| | | va_list argp; |
| | | |
| | | if (!logger || level>logger->level) |
| | | return; |
| | | |
| | | va_start(argp, fmt); |
| | | cp_printout_line(log_str[level], fmt, file, line, argp); |
| | | |
| | | va_end(argp); |
| | | } |
| | | |
| | | #define LINELEN 81 |
| | | #define CHARS_PER_LINE 16 |
| | | static char *print_char = |
| | | " " |
| | | " " |
| | | " !\"#$%&'()*+,-./" |
| | | "0123456789:;<=>?" |
| | | "@ABCDEFGHIJKLMNO" |
| | | "PQRSTUVWXYZ[\\]^_" |
| | | "`abcdefghijklmno" |
| | | "pqrstuvwxyz{|}~ " |
| | | " " |
| | | " " |
| | | " ???????????????" |
| | | "????????????????" |
| | | "????????????????" |
| | | "????????????????" |
| | | "????????????????" |
| | | "????????????????"; |
| | | |
| | | void cp_log_dump(int level, char *buf, int len) |
| | | { |
| | | int rc; |
| | | int idx; |
| | | char prn[LINELEN]; |
| | | char lit[CHARS_PER_LINE + 2]; |
| | | char hc[4]; |
| | | short line_done = 1; |
| | | |
| | | if (!logger || level>logger->level) |
| | | return; |
| | | |
| | | rc = len; |
| | | idx = 0; |
| | | lit[CHARS_PER_LINE] = '\0'; |
| | | |
| | | while (rc > 0) |
| | | { |
| | | if (line_done) |
| | | snprintf(prn, LINELEN, "%08X: ", idx); |
| | | |
| | | do |
| | | { |
| | | unsigned char c = buf[idx]; |
| | | snprintf(hc, 4, "%02X ", c); |
| | | strncat(prn, hc, LINELEN); |
| | | |
| | | lit[idx % CHARS_PER_LINE] = print_char[c]; |
| | | } |
| | | while (--rc > 0 && (++idx % CHARS_PER_LINE != 0)); |
| | | |
| | | line_done = (idx % CHARS_PER_LINE) == 0; |
| | | if (line_done) |
| | | { |
| | | #ifdef DUMPLICATE_OUTPUT |
| | | printf("%s %s\n", prn, lit); |
| | | #endif |
| | | if (logger->fp) |
| | | fprintf(logger->fp, "%s %s\n", prn, lit); |
| | | } |
| | | } |
| | | |
| | | if (!line_done) |
| | | { |
| | | int ldx = idx % CHARS_PER_LINE; |
| | | lit[ldx++] = print_char[(int)buf[idx]]; |
| | | lit[ldx] = '\0'; |
| | | |
| | | while ((++idx % CHARS_PER_LINE) != 0) |
| | | strncat(prn, " ", LINELEN); |
| | | |
| | | #ifdef DUMPLICATE_OUTPUT |
| | | printf("%s %s\n", prn, lit); |
| | | #endif |
| | | if (logger->fp) |
| | | fprintf(logger->fp, "%s %s\n", prn, lit); |
| | | |
| | | } |
| | | } |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2012 Guo Wenxue <guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_logger.h |
| | | * Description: This file is the linux infrastructural logger system library |
| | | * |
| | | * Version: 1.0.0(08/08/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "08/08/2012 05:16:56 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #ifndef __CP_LOG_H |
| | | #define __CP_LOG_H |
| | | |
| | | #include <stdarg.h> |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <string.h> |
| | | #include <unistd.h> |
| | | #include <signal.h> |
| | | #include <time.h> |
| | | #include <errno.h> |
| | | |
| | | #include <pthread.h> |
| | | #include <sys/types.h> |
| | | #include <sys/time.h> |
| | | |
| | | #define LOG_VERSION_STR "1.0.0" |
| | | |
| | | #ifndef FILENAME_LEN |
| | | #define FILENAME_LEN 64 |
| | | #endif |
| | | |
| | | #define DEFAULT_LOGFILE "cp_logger.log" |
| | | #define DBG_LOG_FILE "console" /* Debug mode log file is console */ |
| | | |
| | | #define LOG_ROLLBACK_SIZE 512 /* Default rollback log size */ |
| | | #define LOG_ROLLBACK_NONE 0 /* Set rollback size to 0 will not rollback */ |
| | | |
| | | #define DEFAULT_TIME_FORMAT "%Y-%m-%d %H:%M:%S" |
| | | #define MAX_LOG_MESSAGE_LEN 0x1000 |
| | | |
| | | //#define DUMPLICATE_OUTPUT /* Log to file and printf on console */ |
| | | #define LOG_FILE_LINE /* Log the file and line */ |
| | | |
| | | enum |
| | | { |
| | | LOG_LEVEL_DISB = 0, /* Disable "Debug" */ |
| | | LOG_LEVEL_FATAL, /* Debug Level "Fatal" */ |
| | | LOG_LEVEL_ERROR, /* Debug Level "ERROR" */ |
| | | LOG_LEVEL_WARN, /* Debug Level "warnning" */ |
| | | LOG_LEVEL_NRML, /* Debug Level "Normal" */ |
| | | LOG_LEVEL_DEBUG, /* Debug Level "Debug" */ |
| | | LOG_LEVEL_INFO, /* Debug Level "Information" */ |
| | | LOG_LEVEL_TRACE, /* Debug Level "Trace" */ |
| | | LOG_LEVEL_MAX, |
| | | }; |
| | | |
| | | #define CP_LOGGER_MALLOC 1<<0 |
| | | #define CP_LOGGER_ARGUMENT 0<<0 |
| | | |
| | | #define CP_LOGGER_CONSOLE 1<<1 |
| | | #define CP_LOGGER_FILE 0<<1 |
| | | |
| | | #define CP_LOGGER_LEVEL_OPT 1<<2 /* The log level is sepcified by the command option */ |
| | | typedef struct _cp_logger |
| | | { |
| | | unsigned char flag; /* This logger pointer is malloc() or passed by argument */ |
| | | char file[FILENAME_LEN]; |
| | | int level; |
| | | int size; |
| | | |
| | | FILE *fp; |
| | | } cp_logger; |
| | | |
| | | extern char *log_str[]; |
| | | |
| | | extern cp_logger *cp_log_init(cp_logger *log, char *filename, int level, int log_size); |
| | | extern int cp_log_open(void); |
| | | extern void cp_log_set_time_format(char *time_format); |
| | | extern int cp_log_reopen(void); |
| | | extern void cp_log_term(void); |
| | | extern void cp_log_raw(const char *fmt, ...); |
| | | extern void cp_log(int level, char *fmt, ...); |
| | | extern void cp_log_line(int level, char *file, int line, char *fmt, ...); |
| | | extern void cp_log_str(int level, const char *msg); |
| | | |
| | | extern void cp_log_dump(int level, char *buf, int len); |
| | | |
| | | #ifdef LOG_FILE_LINE |
| | | #define log_trace(fmt, ...) cp_log_line(LOG_LEVEL_TRACE, __FILE__, __LINE__, fmt, ##__VA_ARGS__) |
| | | #define log_info(fmt, ...) cp_log_line(LOG_LEVEL_INFO, __FILE__, __LINE__, fmt, ##__VA_ARGS__) |
| | | #define log_dbg(fmt, ...) cp_log_line(LOG_LEVEL_DEBUG, __FILE__, __LINE__, fmt, ##__VA_ARGS__) |
| | | #define log_nrml(fmt, ...) cp_log_line(LOG_LEVEL_NRML, __FILE__, __LINE__, fmt, ##__VA_ARGS__) |
| | | #define log_warn(fmt, ...) cp_log_line(LOG_LEVEL_WARN, __FILE__, __LINE__, fmt, ##__VA_ARGS__) |
| | | #define log_err(fmt, ...) cp_log_line(LOG_LEVEL_ERROR, __FILE__, __LINE__, fmt, ##__VA_ARGS__) |
| | | #define log_fatal(fmt, ...) cp_log_line(LOG_LEVEL_FATAL, __FILE__, __LINE__, fmt, ##__VA_ARGS__) |
| | | #else |
| | | #define log_trace(fmt, ...) cp_log(LOG_LEVEL_TRACE, fmt, ##__VA_ARGS__) |
| | | #define log_info(fmt, ...) cp_log(LOG_LEVEL_INFO, fmt, ##__VA_ARGS__) |
| | | #define log_dbg(fmt, ...) cp_log(LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__) |
| | | #define log_nrml(fmt, ...) cp_log(LOG_LEVEL_NRML, fmt, ##__VA_ARGS__) |
| | | #define log_warn(fmt, ...) cp_log(LOG_LEVEL_WARN, fmt, ##__VA_ARGS__) |
| | | #define log_err(fmt, ...) cp_log(LOG_LEVEL_ERROR, fmt, ##__VA_ARGS__) |
| | | #define log_fatal(fmt, ...) cp_log(LOG_LEVEL_FATAL, fmt, ##__VA_ARGS__) |
| | | #endif |
| | | |
| | | |
| | | #endif /* __CP_LOG_H */ |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_proc.c |
| | | * Description: This file is the process API |
| | | * |
| | | * Version: 1.0.0(11/06/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "11/06/2012 09:19:02 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <unistd.h> |
| | | #include <libgen.h> |
| | | #include <fcntl.h> |
| | | #include <sys/types.h> |
| | | #include <sys/stat.h> |
| | | #include <pthread.h> |
| | | |
| | | #include "cp_proc.h" |
| | | #include "cp_logger.h" |
| | | |
| | | CP_PROC_SIG g_cp_signal={0}; |
| | | |
| | | void cp_proc_sighandler(int sig) |
| | | { |
| | | switch(sig) |
| | | { |
| | | case SIGINT: |
| | | log_warn("SIGINT - stopping\n"); |
| | | g_cp_signal.stop = 1; |
| | | break; |
| | | |
| | | case SIGTERM: |
| | | log_warn("SIGTERM - stopping\n"); |
| | | g_cp_signal.stop = 1; |
| | | break; |
| | | case SIGSEGV: |
| | | log_warn("SIGSEGV - stopping\n"); |
| | | #if 0 |
| | | if(g_cp_signal.stop) |
| | | exit(0); |
| | | |
| | | g_cp_signal.stop = 1; |
| | | #endif |
| | | break; |
| | | |
| | | case SIGPIPE: |
| | | log_warn("SIGPIPE - warnning\n"); |
| | | break; |
| | | |
| | | default: |
| | | break; |
| | | } |
| | | } |
| | | |
| | | |
| | | void cp_install_proc_signal(void) |
| | | { |
| | | struct sigaction sigact, sigign; |
| | | |
| | | log_nrml("Install default signal handler.\n"); |
| | | |
| | | /* Initialize the catch signal structure. */ |
| | | sigemptyset(&sigact.sa_mask); |
| | | sigact.sa_flags = 0; |
| | | sigact.sa_handler = cp_proc_sighandler; |
| | | |
| | | /* Setup the ignore signal. */ |
| | | sigemptyset(&sigign.sa_mask); |
| | | sigign.sa_flags = 0; |
| | | sigign.sa_handler = SIG_IGN; |
| | | |
| | | sigaction(SIGTERM, &sigact, 0); /* catch terminate signal "kill" command */ |
| | | sigaction(SIGINT, &sigact, 0); /* catch interrupt signal CTRL+C */ |
| | | //sigaction(SIGSEGV, &sigact, 0); /* catch segmentation faults */ |
| | | sigaction(SIGPIPE, &sigact, 0); /* catch broken pipe */ |
| | | #if 0 |
| | | sigaction(SIGCHLD, &sigact, 0); /* catch child process return */ |
| | | sigaction(SIGUSR2, &sigact, 0); /* catch USER signal */ |
| | | #endif |
| | | } |
| | | |
| | | |
| | | /* **************************************************************************** |
| | | * FunctionName: daemonize |
| | | * Description : Set the programe runs as daemon in background |
| | | * Inputs : nodir: DON'T change the work directory to / : 1:NoChange 0:Change |
| | | * noclose: close the opened file descrtipion or not 1:Noclose 0:Close |
| | | * Output : NONE |
| | | * Return : NONE |
| | | * *****************************************************************************/ |
| | | void daemonize(int nochdir, int noclose) |
| | | { |
| | | int retval, fd; |
| | | int i; |
| | | |
| | | /* already a daemon */ |
| | | if (1 == getppid()) |
| | | return; |
| | | |
| | | /* fork error */ |
| | | retval = fork(); |
| | | if (retval < 0) exit(1); |
| | | |
| | | /* parent process exit */ |
| | | if (retval > 0) |
| | | exit(0); |
| | | |
| | | /* obtain a new process session group */ |
| | | setsid(); |
| | | |
| | | if (!noclose) |
| | | { |
| | | /* close all descriptors */ |
| | | for (i = getdtablesize(); i >= 0; --i) |
| | | { |
| | | //if (i != g_logPtr->fd) |
| | | close(i); |
| | | } |
| | | |
| | | /* Redirect Standard input [0] to /dev/null */ |
| | | fd = open("/dev/null", O_RDWR); |
| | | |
| | | /* Redirect Standard output [1] to /dev/null */ |
| | | dup(fd); |
| | | |
| | | /* Redirect Standard error [2] to /dev/null */ |
| | | dup(fd); |
| | | } |
| | | |
| | | umask(0); |
| | | |
| | | if (!nochdir) |
| | | chdir("/"); |
| | | |
| | | return; |
| | | } |
| | | |
| | | /* **************************************************************************** |
| | | * FunctionName: record_daemon_pid |
| | | * Description : Record the running daemon program PID to the file "pid_file" |
| | | * Inputs : pid_file:The record PID file path |
| | | * Output : NONE |
| | | * Return : 0: Record successfully Else: Failure |
| | | * *****************************************************************************/ |
| | | int record_daemon_pid(const char *pid_file) |
| | | { |
| | | struct stat fStatBuf; |
| | | int fd = -1; |
| | | int mode = S_IROTH | S_IXOTH | S_IRGRP | S_IXGRP | S_IRWXU; |
| | | char ipc_dir[64] = { 0 }; |
| | | |
| | | strncpy(ipc_dir, pid_file, 64); |
| | | |
| | | /* dirname() will modify ipc_dir and save the result */ |
| | | dirname(ipc_dir); |
| | | |
| | | /* If folder pid_file PATH doesnot exist, then we will create it" */ |
| | | if (stat(ipc_dir, &fStatBuf) < 0) |
| | | { |
| | | if (mkdir(ipc_dir, mode) < 0) |
| | | { |
| | | log_fatal("cannot create %s: %s\n", ipc_dir, strerror(errno)); |
| | | return -1; |
| | | } |
| | | |
| | | (void)chmod(ipc_dir, mode); |
| | | } |
| | | |
| | | /* Create the process running PID file */ |
| | | mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; |
| | | if ((fd = open(pid_file, O_RDWR | O_CREAT | O_TRUNC, mode)) >= 0) |
| | | { |
| | | char pid[PID_ASCII_SIZE]; |
| | | snprintf(pid, sizeof(pid), "%u\n", (unsigned)getpid()); |
| | | write(fd, pid, strlen(pid)); |
| | | close(fd); |
| | | |
| | | log_dbg("Record PID<%u> to file %s.\n", getpid(), pid_file); |
| | | } |
| | | else |
| | | { |
| | | log_fatal("cannot create %s: %s\n", pid_file, strerror(errno)); |
| | | return -1; |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | /* **************************************************************************** |
| | | * FunctionName: get_daemon_pid |
| | | * Description : Get the daemon process PID from the PID record file "pid_file" |
| | | * Inputs : pid_file: the PID record file |
| | | * Output : NONE |
| | | * Return : pid_t: The daemon process PID number |
| | | * *****************************************************************************/ |
| | | pid_t get_daemon_pid(const char *pid_file) |
| | | { |
| | | FILE *f; |
| | | pid_t pid; |
| | | |
| | | if ((f = fopen(pid_file, "rb")) != NULL) |
| | | { |
| | | char pid_ascii[PID_ASCII_SIZE]; |
| | | (void)fgets(pid_ascii, PID_ASCII_SIZE, f); |
| | | (void)fclose(f); |
| | | pid = atoi(pid_ascii); |
| | | } |
| | | else |
| | | { |
| | | log_fatal("Can't open PID record file %s: %s\n", pid_file, strerror(errno)); |
| | | return -1; |
| | | } |
| | | return pid; |
| | | } |
| | | |
| | | /* **************************************************************************** |
| | | * FunctionName: check_daemon_running |
| | | * Description : Check the daemon program already running or not |
| | | * Inputs : pid_file: The record running daemon program PID |
| | | * Output : NONE |
| | | * Return : 1: The daemon program alread running 0: Not running |
| | | * *****************************************************************************/ |
| | | int check_daemon_running(const char *pid_file) |
| | | { |
| | | int retVal = -1; |
| | | struct stat fStatBuf; |
| | | |
| | | retVal = stat(pid_file, &fStatBuf); |
| | | if (0 == retVal) |
| | | { |
| | | pid_t pid = -1; |
| | | printf("PID record file \"%s\" exist.\n", pid_file); |
| | | |
| | | pid = get_daemon_pid(pid_file); |
| | | if (pid > 0) /* Process pid exist */ |
| | | { |
| | | if ((retVal = kill(pid, 0)) == 0) |
| | | { |
| | | printf("Program with PID[%d] seems running.\n", pid); |
| | | return 1; |
| | | } |
| | | else /* Send signal to the old process get no reply. */ |
| | | { |
| | | printf("Program with PID[%d] seems exit.\n", pid); |
| | | remove(pid_file); |
| | | return 0; |
| | | } |
| | | } |
| | | else if (0 == pid) |
| | | { |
| | | printf("Can not read program PID form record file.\n"); |
| | | remove(pid_file); |
| | | return 0; |
| | | } |
| | | else /* Read pid from file "pid_file" failure */ |
| | | { |
| | | printf("Read record file \"%s\" failure, maybe program still running.\n", pid_file); |
| | | return 1; |
| | | } |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | /* **************************************************************************** |
| | | * FunctionName: set_daemon_running |
| | | * Description : Set the programe running as daemon if it's not running and record |
| | | * its PID to the pid_file. |
| | | * Inputs : pid_file: The record running daemon program PID |
| | | * Output : NONE |
| | | * Return : 0: Successfully. 1: Failure |
| | | * *****************************************************************************/ |
| | | int set_daemon_running(const char *pid_file) |
| | | { |
| | | daemonize(0, 1); |
| | | log_nrml("Program running as daemon [PID:%d].\n", getpid()); |
| | | |
| | | if (record_daemon_pid(pid_file) < 0) |
| | | { |
| | | log_fatal("Record PID to file \"%s\" failure.\n", pid_file); |
| | | return -2; |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | int thread_start(pthread_t * thread_id, THREAD_BODY * thread_workbody, void *thread_arg) |
| | | { |
| | | int retval = 0; |
| | | |
| | | pthread_attr_t thread_attr; |
| | | |
| | | /* Initialize the thread attribute */ |
| | | retval = pthread_attr_init(&thread_attr); |
| | | if(retval) |
| | | return -1; |
| | | |
| | | /* Set the stack size of the thread */ |
| | | retval = pthread_attr_setstacksize(&thread_attr, 120 * 1024); |
| | | if(retval) |
| | | goto CleanUp; |
| | | |
| | | /* Set thread to detached state:Don`t need pthread_join */ |
| | | retval = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); |
| | | if(retval) |
| | | goto CleanUp; |
| | | |
| | | /* Create the thread */ |
| | | retval = pthread_create(thread_id, &thread_attr, thread_workbody, thread_arg); |
| | | if(retval) |
| | | goto CleanUp; |
| | | |
| | | CleanUp: |
| | | /* Destroy the attributes of thread */ |
| | | pthread_attr_destroy(&thread_attr); |
| | | return retval; |
| | | } |
| | | |
| | | |
| | | void exec_system_cmd(const char *format, ...) |
| | | { |
| | | char cmd[256]; |
| | | va_list args; |
| | | int done; |
| | | |
| | | memset(cmd, 0, sizeof(cmd)); |
| | | |
| | | va_start(args, format); |
| | | done = vsnprintf(cmd, sizeof(cmd), format, args); |
| | | va_end(args); |
| | | |
| | | system(cmd); |
| | | } |
| | | |
| | | |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_proc.h |
| | | * Description: This head file is for Linux process API |
| | | * |
| | | * Version: 1.0.0(11/06/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "11/06/2012 09:21:33 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #ifndef __CP_PROC_H |
| | | #define __CP_PROC_H |
| | | |
| | | #include <signal.h> |
| | | |
| | | #define PID_ASCII_SIZE 11 |
| | | |
| | | typedef struct __CP_PROC_SIG |
| | | { |
| | | int signal; |
| | | unsigned stop; /* 0: Not term 1: Stop */ |
| | | } CP_PROC_SIG; |
| | | |
| | | typedef void *(THREAD_BODY) (void *thread_arg); |
| | | |
| | | extern CP_PROC_SIG g_cp_signal; |
| | | extern void cp_install_proc_signal(void); |
| | | |
| | | extern void daemonize(int nochdir, int noclose); |
| | | extern int record_daemon_pid(const char *pid_file); |
| | | extern pid_t get_daemon_pid(const char *pid_file); |
| | | extern int check_daemon_running(const char *pid_file); |
| | | extern int set_daemon_running(const char *pid_file); |
| | | |
| | | extern void exec_system_cmd(const char *format, ...); |
| | | |
| | | extern int thread_start(pthread_t * thread_id, THREAD_BODY * thread_workbody, void *thread_arg); |
| | | |
| | | #endif |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2014 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_socket.c |
| | | * Description: This file |
| | | * |
| | | * Version: 1.0.0(11/18/2014) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "11/18/2014 11:15:04 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | #include <stdio.h> |
| | | #include <unistd.h> |
| | | #include <string.h> |
| | | #include <netdb.h> |
| | | #include <unistd.h> |
| | | #include <fcntl.h> |
| | | |
| | | #include <sys/un.h> |
| | | #include <sys/types.h> |
| | | #include <linux/sockios.h> |
| | | #include <sys/ioctl.h> |
| | | #include <sys/socket.h> |
| | | #include <netinet/in.h> |
| | | #include <arpa/inet.h> |
| | | |
| | | #include "cp_logger.h" |
| | | #include "cp_socket.h" |
| | | |
| | | int cp_sock_set_nonblock(int sockfd) |
| | | { |
| | | int opts; |
| | | /* |
| | | * fcntl may set: |
| | | * |
| | | * EACCES, EAGAIN: Operation is prohibited by locks held by other |
| | | * processes. Or, operation is prohibited because the file has |
| | | * been memory-mapped by another process. |
| | | * EBADF: fd is not an open file descriptor, or the command was F_SETLK |
| | | * or F_SETLKW and the file descriptor open mode doesn't match |
| | | * with the type of lock requested. |
| | | * EDEADLK: It was detected that the specified F_SETLKW command would |
| | | * cause a deadlock. |
| | | * EFAULT: lock is outside your accessible address space. |
| | | * EINTR: For F_SETLKW, the command was interrupted by a signal. For |
| | | * F_GETLK and F_SETLK, the command was interrupted by a signal |
| | | * before the lock was checked or acquired. Most likely when |
| | | * locking a remote file (e.g. locking over NFS), but can |
| | | * sometimes happen locally. |
| | | * EINVAL: For F_DUPFD, arg is negative or is greater than the maximum |
| | | * allowable value. For F_SETSIG, arg is not an allowable signal |
| | | * number. |
| | | * EMFILE: For F_DUPFD, the process already has the maximum number of |
| | | * file descriptors open. |
| | | * ENOLCK: Too many segment locks open, lock table is full, or a remote |
| | | * locking protocol failed (e.g. locking over NFS). |
| | | * EPERM: Attempted to clear the O_APPEND flag on a file that has the |
| | | * append-only attribute set. |
| | | */ |
| | | opts = fcntl(sockfd, F_GETFL); |
| | | if (opts < 0) |
| | | { |
| | | log_warn("fcntl() get socket options failure: %s\n", strerror(errno)); |
| | | return -1; |
| | | } |
| | | |
| | | opts |= O_NONBLOCK; |
| | | if (fcntl(sockfd, F_SETFL, opts) < 0) |
| | | { |
| | | log_warn("fcntl() set socket options failure: %s\n", strerror(errno)); |
| | | return -1; |
| | | } |
| | | |
| | | log_dbg("Set socket[%d] none blocking\n", sockfd); |
| | | return opts; |
| | | } |
| | | |
| | | int cp_sock_connect(cp_sock_t *sock) |
| | | { |
| | | int rv = -1; |
| | | int sock_fd = -1; |
| | | char service[20]; |
| | | struct addrinfo hints, *rp; |
| | | struct addrinfo *res = NULL; |
| | | struct in_addr inaddr; |
| | | char ipstr[20]; |
| | | |
| | | if(!sock) |
| | | { |
| | | log_err("Invalid input argument\n"); |
| | | return -1; |
| | | } |
| | | |
| | | if(SOCK_STAT_CONNECTED == sock->status) |
| | | { |
| | | return 0; |
| | | } |
| | | else if(SOCK_STAT_CONNECTING == sock->status) |
| | | { |
| | | goto connecting; |
| | | } |
| | | |
| | | log_nrml("Start socket connect to [%s:%d]...\n", sock->host, sock->port); |
| | | |
| | | memset(&hints, 0, sizeof(struct addrinfo)); |
| | | hints.ai_family = AF_INET; /* Only support IPv4 */ |
| | | hints.ai_socktype = SOCK_STREAM; |
| | | |
| | | /* If Hostname is a valid IP address, then don't use name resolution */ |
| | | if( inet_aton(sock->host, &inaddr) ) |
| | | { |
| | | log_info("%s is a valid IP address, don't use name resolution.\n", sock->host); |
| | | hints.ai_flags |= AI_NUMERICHOST; |
| | | } |
| | | |
| | | /* Obtain address(es) matching host/port */ |
| | | snprintf(service, sizeof(service), "%d", sock->port); |
| | | if( (rv=getaddrinfo(sock->host, service, &hints, &res)) ) |
| | | { |
| | | log_err("getaddrinfo() parser [%s:%s] failed: %s\n", sock->host, service, gai_strerror(rv)); |
| | | rv = -2; |
| | | goto failed; |
| | | } |
| | | |
| | | |
| | | /* getaddrinfo() returns a list of address structures. Try each |
| | | * address until we successfully connect or bind |
| | | */ |
| | | rv = -3; /* Connect failure */ |
| | | for (rp=res; rp!=NULL; rp=rp->ai_next) |
| | | { |
| | | /* Create the socket */ |
| | | sock_fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); |
| | | if( sock_fd < 0) |
| | | { |
| | | log_err("socket() create failed: %s\n", strerror(errno)); |
| | | rv = -4; |
| | | continue; |
| | | } |
| | | |
| | | inet_ntop(AF_INET, &(((struct sockaddr_in *)(rp->ai_addr))->sin_addr), ipstr, sizeof(ipstr)); |
| | | log_dbg("DNS resolve IP address [%s]\n", ipstr); |
| | | |
| | | cp_sock_set_nonblock(sock_fd); |
| | | |
| | | /* Nono block Connect to the remote server */ |
| | | if(0==connect(sock_fd, rp->ai_addr, rp->ai_addrlen)) |
| | | { |
| | | /* Conenct to server successfully */ |
| | | memcpy(&sock->saddr, &rp->ai_addr, sizeof(sock->saddr)); |
| | | sock->fd = sock_fd; |
| | | sock->status = SOCK_STAT_CONNECTED; |
| | | rv = 0; |
| | | goto connected; |
| | | } |
| | | else |
| | | { |
| | | if(EINPROGRESS == errno) |
| | | { |
| | | /* Connect to server now in progress */ |
| | | memcpy(&sock->saddr, &rp->ai_addr, sizeof(sock->saddr)); |
| | | sock->fd = sock_fd; |
| | | sock->status = SOCK_STAT_CONNECTING; |
| | | rv = 0; |
| | | goto connecting; |
| | | } |
| | | else |
| | | { |
| | | /* Connect to server failed. */ |
| | | close(sock_fd); |
| | | rv = -5; |
| | | log_err("connect() to server failed: %s\n", strerror(errno)); |
| | | goto failed; |
| | | } |
| | | } |
| | | |
| | | close(sock_fd); |
| | | } |
| | | |
| | | |
| | | failed: |
| | | log_err("create socket connect to [%s:%d] failed: %s\n", sock->host, sock->port, strerror(errno)); |
| | | sock->status = SOCK_STAT_DISCONNECT; |
| | | sock->fd = -1; |
| | | return rv; |
| | | |
| | | connecting: |
| | | if(SOCK_STAT_CONNECTING == sock->status) |
| | | { |
| | | int len; |
| | | |
| | | len = sizeof(sock->saddr); |
| | | |
| | | errno = 0; |
| | | if( 0 == connect(sock->fd, &sock->saddr, len) ) |
| | | { |
| | | /* connect() return 0 means it already connected */ |
| | | sock->status = SOCK_STAT_CONNECTED; |
| | | rv = 0; |
| | | goto connected; |
| | | } |
| | | |
| | | /* Connect failure will continue to check */ |
| | | switch (errno) |
| | | { |
| | | case EISCONN: |
| | | sock->status = SOCK_STAT_CONNECTED; |
| | | rv = 0; |
| | | goto connected; |
| | | |
| | | case EALREADY: |
| | | case EINPROGRESS: |
| | | log_dbg("socket[%d] connect to remote [%s:%d] in progress\n", sock->fd, sock->host, sock->port); |
| | | rv = 0; |
| | | goto cleanup; |
| | | |
| | | default: |
| | | log_err("socket[%d] connect to remote [%s:%d] failed: %s\n", sock->fd, sock->host, sock->port, strerror(errno)); |
| | | sock->status = SOCK_STAT_DISCONNECT; |
| | | rv = -7; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | connected: |
| | | if(SOCK_STAT_CONNECTED == sock->status) |
| | | { |
| | | rv = 0; |
| | | log_nrml("socket[%d] connected to remote server [%s:%d]\n", sock->fd, sock->host, sock->port); |
| | | goto cleanup; |
| | | } |
| | | |
| | | cleanup: |
| | | if(res) |
| | | freeaddrinfo(res); /* No longer needed */ |
| | | |
| | | return rv; |
| | | } |
| | | |
| | | void cp_sock_close(cp_sock_t *sock) |
| | | { |
| | | close(sock->fd); |
| | | sock->fd = 0; |
| | | sock->status = SOCK_STAT_INIT; |
| | | } |
| | | |
| | | void cp_sock_term(cp_sock_t *sock) |
| | | { |
| | | close(sock->fd); |
| | | memset(sock, 0, sizeof(*sock)); |
| | | } |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2014 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_socket.h |
| | | * Description: This head file |
| | | * |
| | | * Version: 1.0.0(11/19/2014) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "11/19/2014 12:16:45 AM" |
| | | * |
| | | ********************************************************************************/ |
| | | #ifndef __CP_SOCKET_H_ |
| | | #define __CP_SOCKET_H_ |
| | | |
| | | #include <sys/types.h> |
| | | #include <sys/socket.h> |
| | | |
| | | #define DOMAIN_MAX_LEN 128 |
| | | |
| | | #define SOCK_STAT_INIT 0 |
| | | #define SOCK_STAT_CONNECTING 1 |
| | | #define SOCK_STAT_CONNECTED 2 |
| | | #define SOCK_STAT_DISCONNECT 3 |
| | | |
| | | typedef struct cp_sock_s |
| | | { |
| | | char host[DOMAIN_MAX_LEN]; /* Connect/Listen hostname or IP address */ |
| | | int port; /* Connect/Listen server port */ |
| | | int fd; /* Connected/Listen socket fd */ |
| | | int status; /* Socket connected or not */ |
| | | struct sockaddr saddr; /* sockaddr for none-block connect */ |
| | | |
| | | } cp_sock_t; /*--- end of struct cp_sock_s ---*/ |
| | | |
| | | extern int cp_sock_connect(cp_sock_t *sock); |
| | | extern void cp_sock_close(cp_sock_t *sock); |
| | | extern void cp_sock_term(cp_sock_t *sock); |
| | | #endif |
| | | |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2014 GuoWenxue<guowenxue@email.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cvd_conf.c |
| | | * Description: This file |
| | | * |
| | | * Version: 1.0.0(11/19/2014) |
| | | * Author: GuoWenxue <guowenxue@email.com> |
| | | * ChangeLog: 1, Release initial version on "11/19/2014 01:58:28 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include "cp_logger.h" |
| | | #include "cvd_conf.h" |
| | | #include "cp_iniparser.h" |
| | | |
| | | |
| | | int parser_cvd_conf(char *ini_name, cp_logger *logger, comport_sock_bind_t *cvd_bind) |
| | | { |
| | | dictionary *ini; |
| | | char *str; |
| | | int val, i; |
| | | |
| | | if(!ini_name || !logger || !cvd_bind) |
| | | { |
| | | log_err("Invalid input arguments\n"); |
| | | return -1 ; |
| | | } |
| | | |
| | | ini = iniparser_load(ini_name); |
| | | if (ini==NULL) |
| | | { |
| | | log_err("cannot parse file: %s\n", ini_name); |
| | | return -2 ; |
| | | } |
| | | |
| | | /************************************************ |
| | | * Parser the Logger configuration |
| | | ************************************************/ |
| | | |
| | | log_nrml("Parser configure file %s with original logger file [%s]\n", ini_name, logger->file); |
| | | |
| | | str = iniparser_getstring(ini, "log:file", NULL); |
| | | strncpy(logger->file, (strlen(str)>0 ? str : CVD_DEF_LOG_FILE), FILENAME_LEN); |
| | | log_nrml("Set log file [%d] from configuration.\n", logger->level); |
| | | |
| | | /*If not set the log level from command line, then use the configure one*/ |
| | | if( !(logger->flag&CP_LOGGER_LEVEL_OPT) ) |
| | | { |
| | | val = iniparser_getint(ini, "log:level", -1); |
| | | logger->level = (-1==val ? LOG_LEVEL_NRML : val); |
| | | log_nrml("Set log level[%d] from configuration.\n", logger->level); |
| | | } |
| | | |
| | | /* Set the log maximum file size in the configure file */ |
| | | val = iniparser_getint(ini, "log:size", -1); |
| | | logger->size = -1==val ? CVD_DEF_LOG_SIZE : val; |
| | | log_nrml("Set log size [%dKiB] from configuration\n", logger->size); |
| | | |
| | | if ( cp_log_reopen() ) |
| | | { |
| | | printf("Log file reopen failure, exit now...\n"); |
| | | return -3; |
| | | } |
| | | |
| | | log_nrml("Configure Log file \"%s\" with level [%s], maximum size %d KiB.\n", |
| | | logger->file, log_str[logger->level], logger->size); |
| | | |
| | | |
| | | for(i=0; i<MAX_BIND_TUNNEL; i++) |
| | | { |
| | | char key[64]; |
| | | |
| | | snprintf(key, sizeof(key), "TUNNEL%d:comport", i+1); |
| | | str = iniparser_getstring(ini, key, NULL); |
| | | if( NULL!=str && strlen(str) > 0 ) |
| | | { |
| | | strncpy(cvd_bind->comport_dev, str, DEVNAME_LEN); |
| | | log_info("Configure comport: %s\n", cvd_bind->comport_dev); |
| | | } |
| | | else |
| | | { |
| | | log_err("Configure file lost serial port configuration\n"); |
| | | return -3; |
| | | } |
| | | |
| | | /*----------------------------------------------------------------------------- |
| | | * Connect socket configuration |
| | | *-----------------------------------------------------------------------------*/ |
| | | |
| | | snprintf(key, sizeof(key), "TUNNEL%d:conn_host", i+1); |
| | | str = iniparser_getstring(ini, key, NULL); |
| | | if( NULL!=str && strlen(str) > 0 ) |
| | | { |
| | | char *ptr; |
| | | ptr = strtok(str, ":"); |
| | | if(ptr) |
| | | { |
| | | strncpy(cvd_bind->sock.host, ptr, DOMAIN_MAX_LEN); |
| | | if( NULL != (ptr=strtok(NULL, ":")) ) |
| | | { |
| | | cvd_bind->sock.port = atoi(ptr); |
| | | } |
| | | else |
| | | { |
| | | log_err("Configure file lost connect port configuration\n"); |
| | | return -4; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | log_err("Configure file lost connect host configuration\n"); |
| | | return -5; |
| | | } |
| | | } |
| | | log_nrml("Bind tunnel serial[%s] <==> socket[%s:%d]\n", cvd_bind->comport_dev, cvd_bind->sock.host, cvd_bind->sock.port); |
| | | } |
| | | |
| | | return 0; |
| | | } |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2014 GuoWenxue<guowenxue@email.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cvd_conf.h |
| | | * Description: This head file |
| | | * |
| | | * Version: 1.0.0(11/19/2014) |
| | | * Author: GuoWenxue <guowenxue@email.com> |
| | | * ChangeLog: 1, Release initial version on "11/19/2014 02:28:07 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | #ifndef __CVD_CONF_ |
| | | #define __CVD_CONF_ |
| | | |
| | | #include "cvd_main.h" |
| | | |
| | | #define MAX_BIND_TUNNEL 1 |
| | | |
| | | #define DEF_SERIAL_PORT "/dev/ttyS1" |
| | | //#define DEF_CONN_HOST "192.168.1.78" |
| | | #define DEF_CONN_HOST "emblinux.com" |
| | | #define DEF_CONN_PORT 9001 |
| | | |
| | | #define CVD_DEF_LOG_FILE "/var/log/converterd.log" |
| | | #define CVD_DEF_LOG_SIZE 8 |
| | | |
| | | extern int parser_cvd_conf(char *ini_name, cp_logger *logger, comport_sock_bind_t *cvd_bind); |
| | | |
| | | #endif |
| | | |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2014 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cvd_main.c |
| | | * Description: This file |
| | | * |
| | | * Version: 1.0.0(11/18/2014) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "11/18/2014 10:30:53 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <errno.h> |
| | | #include <string.h> |
| | | #include <unistd.h> |
| | | #include <libgen.h> |
| | | #include <sys/types.h> /* basic system data types */ |
| | | #include <sys/socket.h> /* basic socket definitions */ |
| | | #include <sys/epoll.h> /* epoll function */ |
| | | |
| | | #include "cp_comport.h" |
| | | #include "cp_socket.h" |
| | | #include "cp_logger.h" |
| | | #include "cp_proc.h" |
| | | #include "cvd_conf.h" |
| | | #include "cvd_main.h" |
| | | #include "version.h" |
| | | |
| | | int epoll_add_socket(int epfd, cp_sock_t *sock); |
| | | int epoll_add_comport(int epfd, COM_PORT *comport, char *comport_dev); |
| | | void epoll_del_fd(int epfd, int fd); |
| | | |
| | | static void prog_usage(const char *progname) |
| | | { |
| | | banner(progname); |
| | | |
| | | printf("Usage: %s [OPTION]...\n", progname); |
| | | printf("Receive date from a serial port and transfer the data to remote server by socket.\n"); |
| | | printf("\nMandatory arguments to long options are mandatory for short options too:\n"); |
| | | |
| | | printf(" -d[debug ] Running in debug mode\n"); |
| | | printf(" -l[level ] Set the log level as [0..%d]\n", LOG_LEVEL_MAX-1); |
| | | printf(" -h[help ] Display this help information\n"); |
| | | printf(" -v[version ] Display the program version\n"); |
| | | return ; |
| | | } |
| | | |
| | | int main(int argc, char **argv) |
| | | { |
| | | int i, epfd, nfds, nbytes; |
| | | comport_sock_bind_t cvd_bind; |
| | | cp_logger *logger; |
| | | struct epoll_event evts[MAXEPOLLSIZE]; |
| | | int opt; |
| | | int debug = 0; |
| | | char pid_file[64] = { 0 }; /* The file used to record the PID */ |
| | | char *conf_file = CVD_DEF_CONF_FILE; |
| | | char *log_file; |
| | | int log_level = LOG_LEVEL_TRACE; |
| | | const char *progname=NULL; |
| | | |
| | | struct option long_options[] = { |
| | | {"conf", required_argument, NULL, 'c'}, |
| | | {"debug", no_argument, NULL, 'd'}, |
| | | {"level", required_argument, NULL, 'l'}, |
| | | {"version", no_argument, NULL, 'v'}, |
| | | {"help", no_argument, NULL, 'h'}, |
| | | {NULL, 0, NULL, 0} |
| | | }; |
| | | |
| | | progname = basename(argv[0]); |
| | | /* Parser the command line parameters */ |
| | | while ((opt = getopt_long(argc, argv, "c:dl:vh", long_options, NULL)) != -1) |
| | | { |
| | | switch (opt) |
| | | { |
| | | case 'c': /* Set configure file */ |
| | | conf_file = optarg; |
| | | break; |
| | | |
| | | case 'd': /* Set debug running */ |
| | | debug = 1; |
| | | log_file = DBG_LOG_FILE; |
| | | break; |
| | | |
| | | case 'l': /* Set the log level */ |
| | | i = atoi(optarg); |
| | | log_level = i>LOG_LEVEL_MAX ? LOG_LEVEL_MAX-1 : LOG_LEVEL_MAX-1; |
| | | break; |
| | | |
| | | case 'v': /* Get software version */ |
| | | banner(progname); /* Defined in version.h */ |
| | | return EXIT_SUCCESS; |
| | | |
| | | case 'h': /* Get help information */ |
| | | prog_usage(progname); |
| | | return 0; |
| | | |
| | | default: |
| | | break; |
| | | } /* end of "switch(opt)" */ |
| | | } |
| | | |
| | | memset(&cvd_bind, 0, sizeof(cvd_bind)); |
| | | |
| | | if( !debug ) |
| | | { |
| | | snprintf(pid_file, sizeof(pid_file), "/var/run/%s.pid", progname); |
| | | if( check_daemon_running(pid_file) ) |
| | | { |
| | | printf("Programe already running, exit now.\n"); |
| | | return -1; |
| | | } |
| | | } |
| | | |
| | | if( !(logger=cp_log_init(NULL, log_file, log_level, 0)) || cp_log_open()<0 ) |
| | | { |
| | | printf("Init logger system failed, program exit now...\n"); |
| | | return -1; |
| | | } |
| | | |
| | | if( parser_cvd_conf(conf_file, logger, &cvd_bind) < 0) |
| | | { |
| | | printf("Parser configure file '%s' failed, program exit now...\n", conf_file); |
| | | return -1; |
| | | } |
| | | |
| | | cvd_bind.comport = comport_init(cvd_bind.comport_dev, 115200, "8N1N"); |
| | | if( !cvd_bind.comport ) |
| | | { |
| | | log_err("Init comport '%s' as 115200 8N1N failure\n", cvd_bind.comport_dev); |
| | | return -2; |
| | | } |
| | | |
| | | if( (epfd=epoll_create(MAXEPOLLSIZE)) < 0) |
| | | { |
| | | log_err("epoll_create failure: %s\n", strerror(errno)); |
| | | goto CleanUp; |
| | | } |
| | | |
| | | |
| | | if( !debug ) |
| | | { |
| | | if( set_daemon_running(pid_file) ) |
| | | { |
| | | log_fatal("Set program \"%s\" running as daemon failure.\n", progname); |
| | | goto CleanUp; |
| | | } |
| | | } |
| | | |
| | | cp_install_proc_signal(); |
| | | |
| | | while( !g_cp_signal.stop ) |
| | | { |
| | | /* Open comport if it's not opened */ |
| | | if( !cvd_bind.comport->is_connted ) |
| | | { |
| | | epoll_add_comport(epfd, cvd_bind.comport, cvd_bind.comport_dev); |
| | | } |
| | | |
| | | /* Connect to host if not connected */ |
| | | if( SOCK_STAT_CONNECTED != cvd_bind.sock.status ) |
| | | { |
| | | epoll_add_socket(epfd, &cvd_bind.sock); |
| | | } |
| | | |
| | | /* Epoll wait the added socket event */ |
| | | nfds=epoll_wait(epfd, evts, MAXEPOLLSIZE, EPOLL_TIMEOUT); |
| | | if (nfds < 0) |
| | | { |
| | | log_err("epoll_wait get error: %s\n", strerror(errno)); |
| | | continue; |
| | | } |
| | | |
| | | for (i=0; i<nfds; ++i) |
| | | { |
| | | /* Comport get data arriving event happened */ |
| | | if ( evts[i].data.fd == cvd_bind.comport->fd ) |
| | | { |
| | | nbytes = comport_recv(cvd_bind.comport, cvd_bind.buf, sizeof(cvd_bind.buf), COMPORT_TIMEOUT); |
| | | if( nbytes>0 ) |
| | | { |
| | | if( SOCK_STAT_CONNECTED == cvd_bind.sock.status ) |
| | | { |
| | | log_dbg("Transfer data from comport to socket\n"); |
| | | write(cvd_bind.sock.fd, cvd_bind.buf, nbytes); |
| | | } |
| | | else |
| | | { |
| | | log_err("Receive data from serial port [%s] but socket to [%s:%d] disconnect.\n", |
| | | cvd_bind.comport->dev_name, cvd_bind.sock.host, cvd_bind.sock.port); |
| | | } |
| | | } |
| | | } |
| | | /* Socket get data arriving event happened */ |
| | | else if ( evts[i].data.fd == cvd_bind.sock.fd ) |
| | | { |
| | | nbytes = read(cvd_bind.sock.fd, cvd_bind.buf, sizeof(cvd_bind.buf)); |
| | | /* Socket disconnected */ |
| | | if(nbytes == 0) |
| | | { |
| | | log_warn("Socket[%d] connect to [%s:%d] disconnect\n", |
| | | cvd_bind.sock.fd, cvd_bind.sock.host, cvd_bind.sock.port); |
| | | epoll_del_fd(epfd, evts[i].data.fd); |
| | | cp_sock_close(&cvd_bind.sock); |
| | | } |
| | | /* Socket read error */ |
| | | else if(nbytes < 0) |
| | | { |
| | | log_warn("Read data from socket[%d] get error: %s, close socket now.\n", |
| | | cvd_bind.sock.fd, strerror(errno)); |
| | | epoll_del_fd(epfd, evts[i].data.fd); |
| | | cp_sock_close(&cvd_bind.sock); |
| | | } |
| | | /* Socket read ok then transmiter to serial port */ |
| | | else if( nbytes>0 ) |
| | | { |
| | | if( cvd_bind.comport->is_connted) |
| | | { |
| | | log_dbg("Transfer data from socket to comport\n"); |
| | | write(cvd_bind.comport->fd, cvd_bind.buf, nbytes); |
| | | } |
| | | else |
| | | { |
| | | log_err("Receive data from socket to [%s:%d] but serial port [%s] disconnect.\n", |
| | | cvd_bind.sock.host, cvd_bind.sock.port, cvd_bind.comport->dev_name); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | CleanUp: |
| | | comport_term(cvd_bind.comport); |
| | | cp_log_term(); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | void epoll_del_fd(int epfd, int fd) |
| | | { |
| | | struct epoll_event ev; |
| | | |
| | | log_warn("Remove fd[%d] from epoll\n", fd); |
| | | ev.events = EPOLLIN | EPOLLET; |
| | | epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &ev); |
| | | } |
| | | |
| | | int epoll_add_comport(int epfd, COM_PORT *comport, char *comport_dev) |
| | | { |
| | | int rv = -1; |
| | | struct epoll_event ev; |
| | | |
| | | if( comport_open(comport) < 0 ) |
| | | { |
| | | rv = -2; |
| | | log_err("Open comport '%s' as 115200 8N1N failure\n", comport_dev); |
| | | goto failed; |
| | | } |
| | | |
| | | ev.data.fd = comport->fd; |
| | | ev.events = EPOLLIN | EPOLLET; |
| | | if (epoll_ctl(epfd, EPOLL_CTL_ADD, comport->fd, &ev) < 0) |
| | | { |
| | | rv = -3; |
| | | log_err("epoll add comport fd[%d] failure\n", comport->fd); |
| | | goto failed; |
| | | } |
| | | |
| | | log_nrml("Add comport [%s] to epoll ok\n", comport_dev); |
| | | |
| | | return 0; |
| | | |
| | | failed: |
| | | comport->fd = -1; |
| | | return rv; |
| | | } |
| | | |
| | | |
| | | int epoll_add_socket(int epfd, cp_sock_t *sock) |
| | | { |
| | | struct epoll_event ev; |
| | | |
| | | if(SOCK_STAT_CONNECTED == sock->status) |
| | | return 0; |
| | | |
| | | /* Try to connect to remote server again */ |
| | | cp_sock_connect(sock); |
| | | |
| | | if( SOCK_STAT_CONNECTED != sock->status ) |
| | | { |
| | | return -1; |
| | | } |
| | | |
| | | ev.data.fd = sock->fd; |
| | | ev.events = EPOLLIN | EPOLLET; |
| | | if (epoll_ctl(epfd, EPOLL_CTL_ADD, sock->fd, &ev) < 0) |
| | | { |
| | | log_err("epoll add socket[%d] failure\n", sock->fd); |
| | | return -2; |
| | | } |
| | | |
| | | log_nrml("Add socket[%d] connect to [%s:%d] to epoll ok\n", sock->fd, sock->host, sock->port); |
| | | return 0; |
| | | } |
| | | |
| | | |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2014 GuoWenxue<guowenxue@email.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cvd_main.h |
| | | * Description: This head file |
| | | * |
| | | * Version: 1.0.0(11/19/2014) |
| | | * Author: GuoWenxue <guowenxue@email.com> |
| | | * ChangeLog: 1, Release initial version on "11/19/2014 02:35:33 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #ifndef __CVD_MAIN_H_ |
| | | #define __CVD_MAIN_H_ |
| | | |
| | | #include "cp_comport.h" |
| | | #include "cp_socket.h" |
| | | |
| | | #define CVD_DEF_CONF_FILE "/apps/etc/converterd.conf" |
| | | |
| | | #define MAXEPOLLSIZE 2 |
| | | #define BUF_SIZE 4096 |
| | | |
| | | #define EPOLL_TIMEOUT 2000 |
| | | #define COMPORT_TIMEOUT 100 |
| | | |
| | | |
| | | typedef struct comport_sock_bind_s |
| | | { |
| | | char buf[BUF_SIZE]; /* Comport/Socket receive buffer */ |
| | | char comport_dev[DEVNAME_LEN]; /* Receive/Transmit comport device name */ |
| | | |
| | | COM_PORT *comport; /* Receive/Transmit comport */ |
| | | cp_sock_t sock; /* Connected socket */ |
| | | } comport_sock_bind_t; /* --- end of struct comport_sock_bind_s ---*/ |
| | | |
| | | |
| | | |
| | | #endif |
New file |
| | |
| | | #********************************************************************************* |
| | | # Copyright: (C) 2012 Guo Wenxue<Email:guowenxue@gmail.com> |
| | | # All rights reserved. |
| | | # |
| | | # Filename: Makefile |
| | | # Description: This Makefile used to call function to compile all the C source |
| | | # in current folder and links all the objects file into a excutable |
| | | # binary file. |
| | | # |
| | | # Version: 1.0.0(10/08/2011~) |
| | | # Author: Guo Wenxue <guowenxue@gmail.com> |
| | | # ChangeLog: 1, Release initial version on "10/08/2011 01:29:33 AM" |
| | | # |
| | | #********************************************************************************/ |
| | | |
| | | PWD=$(shell pwd) |
| | | INSTPATH=/tftp |
| | | |
| | | APP_BINARY_NAME = converterd |
| | | ARCH?=arm920t |
| | | #ARCH?=i386 |
| | | |
| | | LINK_MODE=STATIC |
| | | MODE=PRODUCTION |
| | | DEBUG=1 |
| | | |
| | | LDFLAGS+=-lpthread |
| | | CFLAGS+=-Wall -Werror |
| | | |
| | | ifeq ("${MODE}", "PRODUCTION") |
| | | CFLAGS+=-DPRODUCTION_MODE |
| | | endif |
| | | ifdef DEBUG |
| | | CFLAGS+=-g -DDEBUG |
| | | endif |
| | | |
| | | COMPILE_DATE=$(shell date -u +"%Y-%m-%d %H:%M") |
| | | VPATH= . |
| | | SRCS = $(wildcard ${VPATH}/*.c) |
| | | OBJS = $(patsubst %.c,%.o,$(SRCS)) |
| | | |
| | | TMP=$(shell echo $(ARCH) | tr "[A-Z]" "[a-z]") |
| | | ifneq (,$(filter i386,$(TMP))) |
| | | CROSS_COMPILE= |
| | | else |
| | | CROSS_COMPILE=/opt/xtools/arm920t/bin/arm-linux- |
| | | endif |
| | | |
| | | CFLAGS+=-I${PWD} |
| | | |
| | | export CC=${CROSS_COMPILE}gcc |
| | | export CXX=${CROSS_COMPILE}g++ |
| | | export AR=${CROSS_COMPILE}ar |
| | | export AS=${CROSS_COMPILE}as |
| | | export RANLIB=${CROSS_COMPILE}ranlib |
| | | export STRIP=${CROSS_COMPILE}strip |
| | | export CFLAGS |
| | | export LDFLAGS |
| | | export ARCH |
| | | export LINK_MODE |
| | | |
| | | ifeq ("${LINK_MODE}", "STATIC") |
| | | CFLAGS+=--static |
| | | LDFLAGS+=-static |
| | | else |
| | | LDFLAGS+=-ldl |
| | | endif |
| | | |
| | | all: entry version $(APP_BINARY_NAME) |
| | | make install |
| | | |
| | | entry: |
| | | @echo " "; |
| | | @echo " ========================================================="; |
| | | @echo " ** Compile ${APP_BINARY_NAME} for ${ARCH} "; |
| | | @echo " ========================================================="; |
| | | |
| | | version: |
| | | @echo "/* Generated by makefile, don't Edit it by hand */" > version.h |
| | | @echo "#define DATE \"$(COMPILE_DATE)\"" >> version.h |
| | | @echo "#define MAJOR 1" >>version.h |
| | | @echo "#define MINOR 0" >>version.h |
| | | @echo "#define REVER 0" >>version.h |
| | | @if [ -f .svn/entries ] ; then \ |
| | | echo "#define SVNVER `sed -n -e 11p .svn/entries`" >>version.h; \ |
| | | else \ |
| | | echo "#define SVNVER 0" >>version.h; \ |
| | | fi; |
| | | @echo "" >> version.h |
| | | @echo '#define version(progname) printf("%s Version %d.%d.%d Build @%05d (%s)\\n", progname, MAJOR, MINOR, REVER,SVNVER, DATE)' >> version.h |
| | | @echo '#define copyright() printf("Copyright: (C) 2012 Guo Wenxue<Email:guowenxue@gmail.com\\n")' >>version.h |
| | | @echo '#define banner(progname) {version(progname); copyright(); printf("\\n");}' >>version.h |
| | | @echo "" >> version.h |
| | | |
| | | $(APP_BINARY_NAME): $(OBJS) |
| | | $(CC) -o $@ *.c ${LDFLAGS} |
| | | @$(STRIP) $(APP_BINARY_NAME) |
| | | |
| | | tag: |
| | | @ctags --c-kinds=+defglmnstuvx --langmap=c:.c.h.ho.hem.het.hec.hev.him.hit.hic.hiv -R . |
| | | @cscope -Rbq |
| | | |
| | | install: |
| | | @cp $(APP_BINARY_NAME) ${INSTPATH} |
| | | |
| | | clean: |
| | | @rm -f version.h |
| | | @rm -f *.o $(APP_BINARY_NAME) |
| | | @rm -rf *.gdb *.a *.so *.elf* |
| | | |
| | | distclean: clean |
| | | @rm -f tags cscope* |
| | | |
| | | .PHONY: clean entry |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) Guo Wenxue<guowenxue@gmail.com> |
| | | * All ringhts reserved. |
| | | * |
| | | * Filename: at91_ioctl.h |
| | | * Description: ioctl() cmd argument for driver definition here |
| | | * |
| | | * Version: 1.0.0(05/15/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "05/15/2012 04:28:09 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #ifndef __AT91_IOCTL_H |
| | | #define __AT91_IOCTL_H |
| | | |
| | | #include <asm/ioctl.h> |
| | | #ifndef __KERNEL__ |
| | | #include <sys/ioctl.h> |
| | | #endif |
| | | |
| | | /*=========================================================================== |
| | | * Common ioctl command definition |
| | | *===========================================================================*/ |
| | | |
| | | #define PLATDRV_MAGIC 0x60 |
| | | |
| | | /*=========================================================================== |
| | | * ioctl command for all the drivers 0x01~0x0F |
| | | *===========================================================================*/ |
| | | |
| | | /*args is enable or disable*/ |
| | | #define SET_DRV_DEBUG _IO (PLATDRV_MAGIC, 0x01) |
| | | #define GET_DRV_VER _IO (PLATDRV_MAGIC, 0x02) |
| | | |
| | | /*=========================================================================== |
| | | * ioctl command for few ioctl() cmd driver 0x05~0x2F |
| | | *===========================================================================*/ |
| | | |
| | | /* ADC driver */ |
| | | #define GET_BATTERY_STAT _IO (PLATDRV_MAGIC, 0x06) |
| | | #define GET_GMTUBE_VHIGH _IO (PLATDRV_MAGIC, 0x08) |
| | | #define GET_GPRS_VBAT _IO (PLATDRV_MAGIC, 0x09) |
| | | #define GET_ADC_DATA _IO (PLATDRV_MAGIC, 0x10) |
| | | #define SET_ADC_INTERVEL _IO (PLATDRV_MAGIC, 0x11) |
| | | |
| | | |
| | | /* Buzzer driver */ |
| | | #define BUZZER_ON _IO (PLATDRV_MAGIC, 0x12) |
| | | #define BUZZER_BEEP _IO (PLATDRV_MAGIC, 0x13) |
| | | #define BUZZER_OFF _IO (PLATDRV_MAGIC, 0x14) |
| | | #define BUZZER_FREQ _IO (PLATDRV_MAGIC, 0x15) |
| | | |
| | | /* Button driver */ |
| | | #define GET_BUTTON_STATUS _IO (PLATDRV_MAGIC, 0x17) |
| | | |
| | | /* LED driver */ |
| | | #define LED_OFF _IO (PLATDRV_MAGIC, 0x18) |
| | | #define LED_ON _IO (PLATDRV_MAGIC, 0x19) |
| | | #define LED_BLINK _IO (PLATDRV_MAGIC, 0x1A) |
| | | #define TURN_ALL_LED _IO (PLATDRV_MAGIC, 0x1B) |
| | | |
| | | /* Zigbee driver */ |
| | | #define ZIGBEE_RESET _IO (PLATDRV_MAGIC, 0x1E) |
| | | #define ZIGBEE_STATUS _IO (PLATDRV_MAGIC, 0x1F) |
| | | |
| | | /*=========================================================================== |
| | | * ioctl command for GPS/GPRS driver 0x30~0x3F |
| | | *===========================================================================*/ |
| | | #define GSM_SET_POWER _IO (PLATDRV_MAGIC, 0x30) /* Set GPRS power On(1)/Off(0)/Reset(2) */ |
| | | #define GSM_GET_POWER _IO (PLATDRV_MAGIC, 0x31) /* Get current GPRS power status */ |
| | | #define GSM_GET_ADC _IO (PLATDRV_MAGIC, 0x32) /* Get current GPRS power status */ |
| | | |
| | | #define GPS_SET_POWER _IO (PLATDRV_MAGIC, 0x3A) /* Set GPS power On(1)/Off(0) */ |
| | | #define GPS_GET_POWER _IO (PLATDRV_MAGIC, 0x3B) /* Get current GPS power status */ |
| | | |
| | | /*=========================================================================== |
| | | * ioctl command for GM Tube driver 0x40~0x4F |
| | | *===========================================================================*/ |
| | | #define GM_SET_MEASURE_RADI _IO (PLATDRV_MAGIC, 0x40) /* Start/Stop GM tube radioation measurement */ |
| | | #define GM_GET_MEASURE_DOSE _IO (PLATDRV_MAGIC, 0x41) /* Get sample radiation dose, arg=0:get last time, arg=1: Total*/ |
| | | #define GM_SET_DUTY _IO (PLATDRV_MAGIC, 0x42) /* Set GM tube PWM low duty */ |
| | | #define GM_SET_INTERVAL _IO (PLATDRV_MAGIC, 0x43) /* Set GM tube timer interval */ |
| | | #define GM_GET_VOLTAGE _IO (PLATDRV_MAGIC, 0x44) /* Get GM tube high voltage */ |
| | | |
| | | #define GM_SET_POWER _IO (PLATDRV_MAGIC, 0x45) /* Enable/Disable GM tube 3.3V power */ |
| | | #define GM_SET_PWM_TC _IO (PLATDRV_MAGIC, 0x46) /* Start/Stop GM tube pwm output TC*/ |
| | | #define GM_SET_MEASURE_TC _IO (PLATDRV_MAGIC, 0x47) /* Start/Stop GM tube measurement TC */ |
| | | #define GM_SET_TIMER_TC _IO (PLATDRV_MAGIC, 0x48) /* Start/Stop GM tube timer TC*/ |
| | | |
| | | #endif /* End of __AT91_IOCTL_H */ |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_array.c |
| | | * Description: This file is a dynamic array implement |
| | | * |
| | | * Version: 1.0.0(12/20/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "12/20/2012 01:48:27 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include <stdlib.h> |
| | | #include "cp_array.h" |
| | | #include "cp_common.h" |
| | | #include "cp_logger.h" |
| | | |
| | | CP_ARRAY *cp_array_init(CP_ARRAY *array, int size) |
| | | { |
| | | int i; |
| | | |
| | | if( !array ) |
| | | { |
| | | if( !(array=t_malloc(sizeof(*array))) ) |
| | | { |
| | | return NULL; |
| | | } |
| | | else |
| | | { |
| | | memset(array, 0, sizeof(*array)); |
| | | array->flag |= CP_ARRAY_FLAG_MALLOC; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | /* array is a variable,so clear it */ |
| | | memset(array, 0, sizeof(*array)); |
| | | } |
| | | |
| | | array->size = size; |
| | | if( !array->data && !(array->data=(void **)malloc(array->size*sizeof(void *))) ) |
| | | { |
| | | cp_array_term(array); |
| | | return NULL; |
| | | } |
| | | |
| | | for(i=0; i<array->size; i++) |
| | | { |
| | | array->data[i] = NULL; |
| | | } |
| | | |
| | | return array; |
| | | } |
| | | |
| | | void cp_array_term(CP_ARRAY *array) |
| | | { |
| | | if(!array) |
| | | return; |
| | | |
| | | if(array->data) |
| | | t_free(array->data); |
| | | |
| | | if(array->flag&CP_ARRAY_FLAG_MALLOC) |
| | | { |
| | | t_free(array); |
| | | } |
| | | |
| | | return ; |
| | | } |
| | | |
| | | |
| | | int cp_array_add(CP_ARRAY *array, void *data) |
| | | { |
| | | int i; |
| | | void *entry; |
| | | |
| | | if(!array || !data) |
| | | { |
| | | log_err("Invalude input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | /* array already full */ |
| | | if(array->items >= array->size) |
| | | { |
| | | log_err("array is full,can not add data [%p]\n", data); |
| | | return -2; |
| | | } |
| | | |
| | | /* We don't start the array from 0 but 1 */ |
| | | cp_list_array_for_each(array, i, entry) |
| | | { |
| | | if( !entry ) |
| | | { |
| | | log_dbg("Array[%d] add data[%p] ok\n", i, data); |
| | | array->data[i] = data; |
| | | array->items ++; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | return i; |
| | | } |
| | | |
| | | void cp_array_rm_byindex(CP_ARRAY *array, int index) |
| | | { |
| | | /* We don't start the array from 0 but 1 */ |
| | | if(!array || index<0) |
| | | { |
| | | log_err("Invalude input arguments\n"); |
| | | return; |
| | | } |
| | | |
| | | if(array->data[index]) |
| | | { |
| | | array->items --; |
| | | array->data[index] = NULL; |
| | | } |
| | | } |
| | | |
| | | int cp_array_rm_bydata(CP_ARRAY *array, void *data) |
| | | { |
| | | int i, rv = -3; |
| | | void *entry; |
| | | |
| | | if(!array || !data) |
| | | { |
| | | log_err("Invalude input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | if(array->items <= 0) |
| | | { |
| | | log_err("array is empty,can not remove data [%p]\n", data); |
| | | return -2; |
| | | } |
| | | |
| | | /* We don't start the array from 0 but 1 */ |
| | | cp_list_array_for_each(array, i, entry) |
| | | { |
| | | if( entry == data ) |
| | | { |
| | | array->items --; |
| | | array->data[i] = NULL; |
| | | rv = 0; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | return rv; |
| | | } |
| | | |
| | | void cp_array_travel(CP_ARRAY *array) |
| | | { |
| | | int i; |
| | | void *data; |
| | | |
| | | /* We don't start the array from 0 but 1 */ |
| | | cp_list_array_for_each(array, i, data) |
| | | { |
| | | log_dbg("array data[%d] save data [%p]\n", i, data); |
| | | } |
| | | |
| | | return ; |
| | | } |
| | | |
| | | |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_array.h |
| | | * Description: This head file is for the dynaic array implement |
| | | * |
| | | * Version: 1.0.0(12/20/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "12/20/2012 01:49:11 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #ifndef __CP_ARRAY_H |
| | | #define __CP_ARRAY_H |
| | | |
| | | #define CP_ARRAY_FLAG_MALLOC (1<<0) |
| | | typedef struct _CP_ARRAY |
| | | { |
| | | unsigned char flag; |
| | | int size; |
| | | int items; |
| | | void **data; |
| | | } CP_ARRAY; |
| | | |
| | | #define cp_array_is_full(arr) ( (arr)->size-1==(arr)->items ? 1 :0 ) |
| | | #define cp_array_is_empty(arr) ( 0==(arr)->items ? 1 : 0) |
| | | #define cp_array_count(arr) ( (arr)->items ) |
| | | #define cp_array_size(arr) ( (arr)->size-1 ) |
| | | |
| | | #define cp_list_array_for_each(arr, i, entry) for(i=0,entry=arr->data[i]; i<arr->size; ++i,entry=i<arr->size?arr->data[i]:NULL) |
| | | |
| | | |
| | | CP_ARRAY *cp_array_init(CP_ARRAY *array, int size); |
| | | void cp_array_term(CP_ARRAY *array); |
| | | int cp_array_add(CP_ARRAY *array, void *data); |
| | | void cp_array_rm_byindex(CP_ARRAY *array, int index); |
| | | int cp_array_rm_bydata(CP_ARRAY *array, void *data); |
| | | void cp_array_travel(CP_ARRAY *array); |
| | | |
| | | #endif /* __CP_ARRAY_H */ |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) guowenxue <guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_atcmd.c |
| | | * Description: This is file is used to send AT command to GPRS module. |
| | | * |
| | | * Version: 1.0.0(02/02/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "02/02/2012 10:28:44 AM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include "cp_atcmd.h" |
| | | #include "cp_string.h" |
| | | #include "cp_logger.h" |
| | | #include "cp_time.h" |
| | | |
| | | #ifndef ATCMD_REPLY_LEN |
| | | #define ATCMD_REPLY_LEN 512 |
| | | #endif |
| | | |
| | | /* |
| | | * Description: Send the AT command which modem will only reply "OK" or "ERROR", |
| | | * such as AT,ATE0,AT+CNMP=2 etc. |
| | | * |
| | | * Return Value: 0: OK -X: ERROR |
| | | */ |
| | | int send_atcmd_check_ok(COM_PORT *comport, char *atcmd, unsigned long timeout) |
| | | { |
| | | int retval; |
| | | retval = send_atcmd(comport, atcmd, "OK\r\n", "ERROR\r\n", timeout, NULL, 0); |
| | | |
| | | return 0==retval ? 0 : -2; |
| | | } |
| | | |
| | | /* |
| | | * Description: Send the AT command which will reply the value directly in a |
| | | * single line, such as AT+CGMM, AT+CGSN |
| | | * |
| | | * Output Value: Buf: The AT command query value |
| | | * Return Value: 0: OK -X: ERROR |
| | | * |
| | | */ |
| | | int send_atcmd_check_value(COM_PORT *comport, char *atcmd, unsigned long timeout, char *buf, int buf_len) |
| | | { |
| | | int i = 0; |
| | | int retval=0; |
| | | char tmp[ATCMD_REPLY_LEN]; |
| | | char *start; |
| | | |
| | | if(NULL==buf) |
| | | { |
| | | log_err("Function call arguments error!\n"); |
| | | return -1; |
| | | } |
| | | |
| | | memset(tmp, 0, sizeof(tmp)); |
| | | retval = send_atcmd(comport, atcmd, "OK\r\n", "ERROR\r\n", timeout, tmp, sizeof(tmp)); |
| | | if( 0 != retval) |
| | | { |
| | | return -2; /* AT command can not get reply */ |
| | | } |
| | | |
| | | /* Parser the receive string to get the expect value*/ |
| | | if(NULL != (start=strchr(tmp, '\n')) ) |
| | | { |
| | | start ++; /* Skip '\n' character */ |
| | | while(*start!='\r' && i<buf_len-1) |
| | | { |
| | | buf[i++] = *start; |
| | | start ++; |
| | | } |
| | | } |
| | | buf[i] = '\0'; /* End of the string */ |
| | | |
| | | return ('\0'==buf[0] ? -3 : 0); |
| | | } |
| | | |
| | | /* |
| | | * Description: Send the AT command which will reply the value with a prefix "+CMD: " |
| | | * single line, such as AT+CGMR AT+CPIN? AT+CNMP? AT+CSQ |
| | | * |
| | | * Output Value: Buf: The AT command query value by remove "+XXX:" prefix |
| | | * Return Value: 0: OK -X: ERROR |
| | | * |
| | | */ |
| | | int send_atcmd_check_request(COM_PORT *comport, char *atcmd, unsigned long timeout, char *buf, int buf_len) |
| | | { |
| | | int retval; |
| | | int i = 0; |
| | | char tmp[ATCMD_REPLY_LEN]; |
| | | char *ptr = NULL; |
| | | |
| | | if(NULL==buf) |
| | | { |
| | | log_err("%s() call arguments error!\n", __FUNCTION__); |
| | | return -1; |
| | | } |
| | | |
| | | memset(tmp, 0, sizeof(tmp)); |
| | | retval = send_atcmd(comport, atcmd, "OK\r\n", "ERROR\r\n", timeout, tmp, sizeof(tmp)); |
| | | if( 0 != retval) |
| | | { |
| | | return -2; |
| | | } |
| | | |
| | | /* Parser the receive string to get the expect value*/ |
| | | if(NULL != (ptr=strchr (tmp, ':')) ) |
| | | { |
| | | ptr += 2; /* Skip the ':' and SPACE character */ |
| | | while(*ptr!='\r' && i<buf_len-1) |
| | | { |
| | | buf[i++] = *ptr; |
| | | ptr ++; |
| | | } |
| | | } |
| | | buf[i] = '\0'; /* End of the string */ |
| | | |
| | | return ('\0'==buf[0] ? -3 : 0); |
| | | } |
| | | |
| | | |
| | | /* |
| | | * Description: Send ATE0 command to the GSM module to check GSM module ready or not |
| | | * Return Value: 0: Success !0:Failure |
| | | */ |
| | | int atcmd_check_at_ready(COM_PORT *comport) |
| | | { |
| | | int retval; |
| | | retval=send_atcmd_check_ok(comport, "ATE0\r", 500); |
| | | if(retval) |
| | | { |
| | | log_err("ATE0 check AT command ready [FAILED]\n"); |
| | | } |
| | | else |
| | | log_nrml("ATE0 check AT command ready [OK]\n"); |
| | | |
| | | return retval; |
| | | } |
| | | |
| | | /* |
| | | * Description: Send AT+CPIN? command to the GSM module to check SIM card exist or not |
| | | * Return Value: 0: Success !0:Failure |
| | | */ |
| | | int atcmd_check_sim_valid(COM_PORT *comport) |
| | | { |
| | | int retval = 0; |
| | | char recv_buf[ATCMD_REPLY_LEN]; |
| | | |
| | | retval = send_atcmd_check_request(comport, "AT+CPIN?\r", 800, recv_buf, sizeof(recv_buf)); |
| | | if(0x00 != retval) |
| | | { |
| | | retval = 1; |
| | | log_warn("AT+CPIN? Check SIM Validation: [FAILED]\n"); |
| | | return retval; |
| | | } |
| | | |
| | | if(strstr(recv_buf, "READY")) |
| | | { |
| | | log_nrml("AT+CPIN? Check SIM Validataion: [OK]\n"); |
| | | return 0; |
| | | } |
| | | else |
| | | return -1; |
| | | } |
| | | |
| | | /* Send AT+CSQ command to check GPRS signal*/ |
| | | int atcmd_check_gprs_signal(COM_PORT *comport) |
| | | { |
| | | char recv_buf[ATCMD_REPLY_LEN]; |
| | | int retval; |
| | | int signal = -1; |
| | | |
| | | memset(recv_buf, 0, sizeof(recv_buf)); |
| | | retval = send_atcmd_check_request(comport, "AT+CSQ\r", 3000, recv_buf, sizeof(recv_buf)); |
| | | if( 0 != retval) |
| | | { |
| | | log_err("AT+CSQ Check Signal Strength: [FAILED]\n"); |
| | | return retval; |
| | | } |
| | | |
| | | split_string_to_value(recv_buf, "%d,%d", &signal, NULL); |
| | | |
| | | log_nrml("AT+CSQ Check Signal Strength: [%d]\n", signal); |
| | | |
| | | return signal; |
| | | } |
| | | |
| | | /* Send AT+CREG? command to check SIM card register status */ |
| | | int atcmd_check_gprs_register(COM_PORT *comport) |
| | | { |
| | | int retval, stat = -1; |
| | | char recv_buf[ATCMD_REPLY_LEN]; |
| | | |
| | | memset(recv_buf, 0, sizeof(recv_buf)); |
| | | retval = send_atcmd_check_request(comport, "AT+CREG?\r", 3000, recv_buf, sizeof(recv_buf)); |
| | | if( 0 != retval) |
| | | { |
| | | log_err("AT+CREG? Check SIM card Register: [FAILED]\n"); |
| | | return stat; |
| | | } |
| | | |
| | | split_string_to_value(recv_buf, "%d,%d", NULL, &stat); |
| | | log_nrml("AT+CREG? Check SIM Card Register: [%d]\n", stat); |
| | | |
| | | return stat; |
| | | } |
| | | |
| | | |
| | | int atcmd_check_gprs_carrier(COM_PORT *comport, char *carrier) |
| | | { |
| | | int retval; |
| | | char recv_buf[ATCMD_REPLY_LEN]; |
| | | |
| | | if(carrier == NULL) |
| | | { |
| | | return -1; |
| | | } |
| | | |
| | | retval = send_atcmd_check_request(comport, "AT+COPS?\r", 5000, recv_buf, sizeof(recv_buf)); |
| | | if(retval) |
| | | { |
| | | log_warn("AT+COPS? Check SIM Card Carrier: [FAILED]\n"); |
| | | return retval; |
| | | } |
| | | |
| | | split_string_to_value(recv_buf, "%d,%d,%s,%d", NULL, NULL, carrier, NULL); |
| | | del_char_from_string(carrier, '\"'); |
| | | |
| | | log_nrml("AT+COPS? Check SIM Card Carrier: [%s]\n", carrier); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int atcmd_check_gprs_mcc_mnc(COM_PORT *comport, char *mcc_mnc) |
| | | { |
| | | int retval; |
| | | char recv_buf[ATCMD_REPLY_LEN]; |
| | | int status; |
| | | char mcc[5]; |
| | | char mnc[5]; |
| | | char *ptr = NULL; |
| | | |
| | | retval=send_atcmd_check_ok(comport, "AT+QENG=1\r", 1000); |
| | | if(retval) |
| | | { |
| | | log_err("Send AT command AT+QENG=1 failure\n"); |
| | | return retval; |
| | | } |
| | | |
| | | retval = send_atcmd(comport, "AT+QENG?\r", "OK\r\n", "ERROR\r\n", 5000, recv_buf, sizeof(recv_buf)); |
| | | if(retval) |
| | | { |
| | | log_err("AT+QENG? Check GPRS MCC and MNC failure\n"); |
| | | return retval; |
| | | } |
| | | |
| | | /* AT+QENG? respond value: |
| | | * +QENG: 1,0 |
| | | * +QENG: 0,460,00,7108,80c4,554,41,-95,18,50,0,10,x,x,x,x,x,x,x |
| | | */ |
| | | if(NULL != (ptr=strrchr (recv_buf, ':')) ) |
| | | { |
| | | split_string_to_value(ptr, "%d,%s,%s,%s", &status, mcc, mnc, NULL); |
| | | if(!status) |
| | | { |
| | | sprintf(mcc_mnc, "%s-%s", mcc, mnc); |
| | | log_nrml("AT+QGSMLOC=1 Check GPRS Location MCC-MNC: %s\n", mcc_mnc); |
| | | return 0; |
| | | } |
| | | } |
| | | |
| | | printf("ptr: %s\n", ptr); |
| | | |
| | | return -1; |
| | | } |
| | | |
| | | |
| | | int atcmd_check_gprs_location(COM_PORT *comport, GPRS_LOCATION *loc) |
| | | { |
| | | int retval; |
| | | char recv_buf[ATCMD_REPLY_LEN]; |
| | | int status; |
| | | |
| | | retval=send_atcmd_check_ok(comport, "AT+QIFGCNT=0\r", 1000); |
| | | if(retval) |
| | | { |
| | | log_warn("Send AT command AT+QIFGCNT=0 failure\n"); |
| | | return retval; |
| | | } |
| | | |
| | | retval = send_atcmd_check_request(comport, "AT+QGSMLOC=1\r", 10000, recv_buf, sizeof(recv_buf)); |
| | | if(retval) |
| | | { |
| | | log_warn("AT+QGSMLOC=1 Check GPRS Location: [FAILED]\n"); |
| | | return retval; |
| | | } |
| | | |
| | | /* +QGSMLOC: 0,114.389210,30.500380,2013/01/16,14:03:12, it's GMT time */ |
| | | split_string_to_value(recv_buf, "%d,%s,%s,%s,%s", &status, loc->longitude, loc->latitude, loc->date, loc->time); |
| | | |
| | | if(status) /* Get LOC failure */ |
| | | { |
| | | memset(loc->longitude, 0, sizeof(loc->longitude)); |
| | | memset(loc->latitude, 0, sizeof(loc->latitude)); |
| | | memset(loc->date, 0, sizeof(loc->date)); |
| | | memset(loc->time, 0, sizeof(loc->time)); |
| | | log_warn("AT+QGSMLOC=1 Check GPRS Location failure: %s\n", recv_buf); |
| | | return -1; |
| | | } |
| | | |
| | | log_nrml("GPRS location result=%d latitude,longitude: [%s,%s]\n", status, loc->latitude, loc->longitude); |
| | | log_nrml("GPRS Date and time: %s,%s\n", loc->date, loc->time); |
| | | |
| | | return retval; |
| | | } |
| | | |
| | | |
| | | int atcmd_set_network_mode(COM_PORT *comport, int mode) |
| | | { |
| | | int retval; |
| | | char atcmd[64]={0}; |
| | | |
| | | sprintf (atcmd, "AT+CNMP=%d\r", mode); |
| | | if(0 != (retval=send_atcmd_check_ok(comport, atcmd, 3000)) ) |
| | | { |
| | | log_warn("AT+CNMP Set Network Mode as %d: [FAILED]\n", mode); |
| | | return retval; |
| | | } |
| | | log_nrml("AT+CNMP=%d Set Network Mode: [OK]\n", mode); |
| | | |
| | | /* AT+CNAOP=?: 0->Automatic, 1->GSM,WCDMA, 2->WCDMA,GSM */ |
| | | strncpy (atcmd, "AT+CNAOP=2\r", sizeof(atcmd)); |
| | | if(0 != (retval=send_atcmd_check_ok(comport, atcmd, 3000)) ) |
| | | { |
| | | log_warn("AT+CNAOP=2 Set Acquisitions order preference to WCDMA,GSM [FAILED]\n"); |
| | | return retval; |
| | | } |
| | | log_nrml("AT+CNAOP=2 Set Network Preference [OK]\n"); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int atcmd_check_gprs_name(COM_PORT *comport, char *name) |
| | | { |
| | | int retval; |
| | | char recv_buf[ATCMD_REPLY_LEN]; |
| | | |
| | | if(name == NULL) |
| | | { |
| | | return -1; |
| | | } |
| | | |
| | | retval = send_atcmd_check_value(comport, "AT+CGMM\r", 5000, recv_buf, sizeof(recv_buf)); |
| | | if(retval) |
| | | { |
| | | log_warn("AT+CGMM Check GPRS Module Name: [FAILED]\n"); |
| | | return retval; |
| | | } |
| | | |
| | | strcpy(name, recv_buf); |
| | | |
| | | log_nrml("AT+CGMM Check GPRS Module Name: [%s]\n", name); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | int atcmd_check_gprs_version(COM_PORT *comport, char *version) |
| | | { |
| | | int retval; |
| | | char recv_buf[ATCMD_REPLY_LEN]; |
| | | |
| | | if(version == NULL) |
| | | { |
| | | return -1; |
| | | } |
| | | |
| | | retval = send_atcmd_check_request(comport, "AT+CGMR\r", 5000, recv_buf, sizeof(recv_buf)); |
| | | if(retval) |
| | | { |
| | | log_warn("AT+CGMR Check GPRS Module Version: [FAILED]\n"); |
| | | return retval; |
| | | } |
| | | |
| | | strcpy(version, recv_buf); |
| | | log_nrml("AT+CGMR Check GPRS Module Version: [%s]\n", version); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int atcmd_check_gprs_iemi(COM_PORT *comport, char *iemi) |
| | | { |
| | | int retval; |
| | | char recv_buf[ATCMD_REPLY_LEN]; |
| | | |
| | | if(iemi == NULL) |
| | | { |
| | | return -1; |
| | | } |
| | | |
| | | retval = send_atcmd_check_value(comport, "AT+CGSN\r", 5000, recv_buf, sizeof(recv_buf)); |
| | | if(retval) |
| | | { |
| | | log_warn("AT+CGSN Check GPRS Module IEMI: [FAILED]\n"); |
| | | return retval; |
| | | } |
| | | |
| | | strcpy(iemi, recv_buf); |
| | | log_nrml("AT+CGSN Check GPRS Module IEMI: [%s]\n", iemi); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | int atcmd_check_gprs_network(COM_PORT *comport, int *network) |
| | | { |
| | | int retval; |
| | | char recv_buf[ATCMD_REPLY_LEN]; |
| | | |
| | | if(network == NULL) |
| | | { |
| | | return -1; |
| | | } |
| | | |
| | | retval = send_atcmd_check_request(comport, "AT+CNSMOD?\r", 5000, recv_buf, sizeof(recv_buf)); |
| | | if(retval) |
| | | { |
| | | log_warn("AT+CNSMOD Check Network Mode: [FAILED]\n"); |
| | | return retval; |
| | | } |
| | | |
| | | split_string_to_value(recv_buf, "%d,%d", NULL, network); |
| | | |
| | | log_nrml("AT+CNSMOD? Check Network Mode: [%d]\n", *network); |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | int atcmd_set_apn(COM_PORT *comport, char *apn) |
| | | { |
| | | char atcmd[64]={0}; |
| | | int retval; |
| | | |
| | | sprintf (atcmd, "AT+CGDCONT=1,\"IP\",\"%s\"\r", apn); |
| | | if(0 != (retval=send_atcmd_check_ok(comport, atcmd, 2000)) ) |
| | | { |
| | | log_err("AT+CGDCONT Set APN as \"%s\" [FAILED]\n", apn); |
| | | return retval; |
| | | } |
| | | |
| | | log_nrml("AT+CGDCONT Set APN as \"%s\" [OK]\n"); |
| | | return retval; |
| | | } |
| | | |
| | | |
| | | unsigned char at_match (char *p_pcStr, char *p_pcMatch) |
| | | { |
| | | char acBuf [256], |
| | | *pcStart = NULL, |
| | | *pcTab = NULL; |
| | | |
| | | pcStart = p_pcMatch; |
| | | |
| | | while (0 != pcStart) |
| | | { |
| | | memset (acBuf, 0x00, sizeof (acBuf)); |
| | | |
| | | pcTab = strchr (pcStart, 9); // Find for TAB |
| | | if (0 != pcTab) |
| | | { |
| | | if (pcTab != pcStart) |
| | | { |
| | | strncpy (acBuf, pcStart, pcTab - pcStart); |
| | | } |
| | | pcStart = (0 != *(++pcTab)) ? pcTab : 0; |
| | | } |
| | | else |
| | | { |
| | | strcpy (acBuf, pcStart); |
| | | pcStart = NULL; |
| | | } |
| | | if (0 != acBuf [0] && 0 != strstr (p_pcStr, acBuf)) |
| | | { |
| | | return 0x00; |
| | | } |
| | | } |
| | | return 0x01; |
| | | } |
| | | |
| | | |
| | | /*========================================================================================================= |
| | | * Parameter Description: |
| | | * COM_PORT *comport: The GPRS module data port(/dev/ttyS2); |
| | | * char *atCmd: The AT command which will be sent to GPRS module |
| | | * char *expect: The EXPECT reply string by GPRS module for the AT command, such as "OK" |
| | | * char *error: The ERROR reply string by GPRS module for the AT command, such as "ERROR" |
| | | * unsigned long timeout: Read from data port timeout value |
| | | * char reply: The AT command reply output buffer |
| | | * int reply_len: The AT command reply output buffer length |
| | | * |
| | | * Return Value: |
| | | * int retval: 0->command send OK and "expect" string mached. !0->failure |
| | | * char *content: The AT command reply string by modem. |
| | | * |
| | | *=========================================================================================================*/ |
| | | |
| | | int send_atcmd(COM_PORT *comport, char *atCmd, char *expect, char *error, |
| | | unsigned long timeout, char *reply, int reply_len) |
| | | { |
| | | int retval = -1; |
| | | unsigned long delay = 200; |
| | | unsigned long gap = 300; |
| | | unsigned long ulStartTime; |
| | | |
| | | int iCmdLen = 0, |
| | | iRecvLen = 0, |
| | | iRecvSize = 0, |
| | | iSize = 0; |
| | | |
| | | |
| | | char acRecv[1024]; |
| | | char *pcRecvPtr = NULL; |
| | | |
| | | if(comport->is_connted != 0x01) /* Comport not opened */ |
| | | { |
| | | log_dbg("Comport not opened.\n"); |
| | | return -1; |
| | | } |
| | | |
| | | #if 0 |
| | | /*========================================= |
| | | *= Pause a while before send AT command = |
| | | *=========================================*/ |
| | | if(0 != delay) |
| | | { |
| | | ulStartTime = time_now(); |
| | | while (time_elapsed(ulStartTime) < delay) |
| | | { |
| | | micro_second_sleep(1); |
| | | } |
| | | } |
| | | #endif |
| | | |
| | | /*==================== |
| | | *= Throw Rubbish = |
| | | *====================*/ |
| | | ulStartTime = time_now(); |
| | | memset(&acRecv, 0, sizeof(acRecv)); |
| | | |
| | | while (time_elapsed(ulStartTime) < delay) |
| | | { |
| | | iSize = comport_recv(comport, acRecv, 1, 50); |
| | | if(iSize <= 0) |
| | | { |
| | | break; |
| | | } |
| | | micro_second_sleep(1); |
| | | } |
| | | |
| | | /*==================== |
| | | *= Send AT command = |
| | | *====================*/ |
| | | |
| | | iCmdLen = strlen(atCmd); |
| | | retval = comport_send (comport, atCmd, iCmdLen); |
| | | if (0 != retval) |
| | | { |
| | | retval = 0x02; |
| | | goto CleanUp; |
| | | } |
| | | |
| | | /*=================================================== |
| | | *= Pause a while before read command response. |
| | | *===================================================*/ |
| | | if(0 != gap) |
| | | { |
| | | ulStartTime = time_now(); |
| | | while (time_elapsed(ulStartTime) < gap) |
| | | { |
| | | micro_second_sleep(1); |
| | | } |
| | | } |
| | | |
| | | memset (acRecv, 0, sizeof (acRecv)); |
| | | pcRecvPtr = acRecv; |
| | | iRecvLen = 0; |
| | | iRecvSize = sizeof (acRecv); |
| | | |
| | | retval = -1; |
| | | ulStartTime = time_now(); |
| | | |
| | | while (time_elapsed(ulStartTime) < timeout) |
| | | { |
| | | if ( iRecvLen < (iRecvSize-1) ) |
| | | { |
| | | iSize = comport_recv (comport, pcRecvPtr, 1, 50); |
| | | if (iSize >0) |
| | | { |
| | | iRecvLen += iSize; |
| | | pcRecvPtr += iSize; |
| | | acRecv [iRecvSize-1] = 0; |
| | | |
| | | /*======================================== |
| | | * Match the received with expect String = |
| | | *========================================*/ |
| | | if(NULL != expect) |
| | | { |
| | | if (0x00 == at_match(acRecv, expect)) |
| | | { |
| | | retval = 0; |
| | | goto CleanUp; |
| | | } |
| | | } |
| | | |
| | | /*======================================== |
| | | * Match the received with error String = |
| | | *========================================*/ |
| | | if(NULL != error) |
| | | { |
| | | if (0x00 == at_match(acRecv, error)) |
| | | { |
| | | retval = -3; |
| | | goto CleanUp; |
| | | } |
| | | } |
| | | } /*End of (iSize > 0) */ |
| | | } /* End of (iRecvLen < (iRecvSize-1)) */ |
| | | |
| | | micro_second_sleep(1); |
| | | } /* End of time_elapsed(ulStartTime) < timeout */ |
| | | |
| | | |
| | | if(NULL==expect) |
| | | retval = 0x00; |
| | | else |
| | | retval = -4; |
| | | |
| | | CleanUp: |
| | | //printf("acRecv:\n %s\n", acRecv); |
| | | if( NULL != reply) |
| | | { |
| | | strncpy(reply, acRecv, reply_len); |
| | | } |
| | | |
| | | #if 1 /* Log the command result to log system */ |
| | | { |
| | | char log[512] = {0}; |
| | | snprintf(log, 512, "Send AT command: \"%s\" get reply \"%s\"", atCmd, acRecv); |
| | | int i = 0; |
| | | for (i=0; i<512; i++) |
| | | { |
| | | if('\r'==log[i] || '\n'==log[i] || '\t'==log[i]) |
| | | { |
| | | log[i]=' '; |
| | | } |
| | | else if (0 == log[i]) |
| | | { |
| | | break; |
| | | } |
| | | } |
| | | log_info("%s\n", log); |
| | | } |
| | | #endif |
| | | |
| | | return retval; |
| | | } |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) guowenxue <guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: atcmd.h |
| | | * Description: This is the head file for atcmd.c |
| | | * |
| | | * Version: 1.0.0(05/15/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "05/15/2012 05:31:10 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #ifndef __CP_ATCMD_H |
| | | #define __CP_ATCMD_H |
| | | |
| | | #include "cp_comport.h" |
| | | |
| | | /* AT+CPSI command return important result*/ |
| | | typedef struct _GPRS_LOCATION |
| | | { |
| | | char longitude[15]; |
| | | char latitude[15]; |
| | | char date[15]; |
| | | char time[15]; |
| | | char mcc_mnc[16];/* Mobile Country Code, China is 460 */ |
| | | } GPRS_LOCATION; |
| | | |
| | | typedef struct _REGISTER_INFO |
| | | { |
| | | int type; /* SIM card register type: REG_HOMEWORK,REG_SEARCHING... */ |
| | | int signal; /* GPRS signal */ |
| | | char carrier[64];/* Network operator */ |
| | | GPRS_LOCATION loc; /* Location */ |
| | | } REGISTER_INFO; |
| | | |
| | | |
| | | typedef struct _HARDWARE_INFO |
| | | { |
| | | char model[64]; /* AT+CGMM check GPRS module model */ |
| | | char mrev[64]; /* AT+CGMR check GPRS module revision */ |
| | | char iemi[64]; /* AT+CGSN check GPRS module IEMI(International Mobile station Equipment Identity) number */ |
| | | } HW_INFO; |
| | | |
| | | extern int send_atcmd(COM_PORT *st_comport, char *atCmd, char *expect, char *error, |
| | | unsigned long timeout, char *reply, int reply_len); |
| | | |
| | | extern int send_atcmd_check_ok(COM_PORT *comport, char *atcmd, unsigned long timeout); |
| | | extern int send_atcmd_check_value(COM_PORT *comport, char *atcmd, unsigned long timeout, char *buf, int buf_len); |
| | | extern int send_atcmd_check_request(COM_PORT *comport, char *atcmd, unsigned long timeout, char *buf, int buf_len); |
| | | |
| | | |
| | | extern int atcmd_check_at_ready(COM_PORT *comport); /* Send ATE0 command */ |
| | | extern int atcmd_check_sim_valid(COM_PORT *comport); /* Send AT+CPIN? command */ |
| | | extern int atcmd_check_gprs_signal(COM_PORT *comport); /* Send AT+CSQ command */ |
| | | extern int atcmd_check_gprs_register(COM_PORT *comport); |
| | | extern int atcmd_check_gprs_carrier(COM_PORT *comport, char *carrier); |
| | | extern int atcmd_check_gprs_name(COM_PORT *comport, char *name); |
| | | extern int atcmd_check_gprs_version(COM_PORT *comport, char *version); |
| | | extern int atcmd_check_gprs_iemi(COM_PORT *comport, char *iemi); |
| | | extern int atcmd_check_gprs_network(COM_PORT *comport, int *network); |
| | | extern int atcmd_check_gprs_location(COM_PORT *comport, GPRS_LOCATION *location); |
| | | extern int atcmd_check_gprs_mcc_mnc(COM_PORT *comport, char *mcc_mnc); |
| | | |
| | | extern int atcmd_set_network_mode(COM_PORT *comport, int mode); |
| | | extern int atcmd_set_apn(COM_PORT *comport, char *apn); |
| | | |
| | | #endif /* _CP_ATCMD_H */ |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_common.h |
| | | * Description: This head file is for some common definition |
| | | * |
| | | * Version: 1.0.0(11/13/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "11/13/2012 01:48:01 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #ifndef __CP_COMMON_H |
| | | #define __CP_COMMON_H |
| | | |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <string.h> |
| | | |
| | | #ifndef offsetof |
| | | #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) |
| | | #endif |
| | | |
| | | #define container_of(ptr, type, member) ({ \ |
| | | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ |
| | | (type *)( (char *)__mptr - offsetof(type,member) );}) |
| | | |
| | | //#define MEM_LEAK_CHECK |
| | | |
| | | static inline void *_t_malloc(size_t size |
| | | #ifdef MEM_LEAK_CHECK |
| | | , const char *file, unsigned int line |
| | | #endif |
| | | ) |
| | | { |
| | | void *ptr; |
| | | |
| | | if ((ptr = malloc (size))) |
| | | memset (ptr, 0, size); |
| | | #ifdef MEM_LEAK_CHECK |
| | | printf ("MALLOC,0x%p @%s:%u\n", ptr, file, line); |
| | | #endif |
| | | return ptr; |
| | | } |
| | | |
| | | static inline void _t_free(void *ptr |
| | | #ifdef MEM_LEAK_CHECK |
| | | , const char *file, unsigned int line |
| | | #endif |
| | | ) |
| | | { |
| | | #ifdef MEM_LEAK_CHECK |
| | | printf ("FREE,0x%p @%s:%u\n", ptr, file, line); |
| | | #endif |
| | | free(ptr); |
| | | } |
| | | |
| | | #ifdef MEM_LEAK_CHECK |
| | | #define t_free(p) if(p){ _t_free(p, __FILE__, __LINE__); p=NULL; } |
| | | #define t_malloc(s) _t_malloc(s, __FILE__, __LINE__) |
| | | #else |
| | | #define t_free(p) if(p){ _t_free(p); p=NULL; } |
| | | #define t_malloc(s) _t_malloc(s) |
| | | #endif |
| | | |
| | | #endif |
| | | |
New file |
| | |
| | | /* ******************************************************************************** |
| | | * Copyright: (C) 2012 Guo Wenxue <guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_comport.c |
| | | * Description: It's the comport operate library. |
| | | * |
| | | * Version: 1.0.0(10/17/2011~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "10/17/2011 03:33:25 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include "cp_comport.h" |
| | | |
| | | /************************************************************************************** |
| | | * Description: Set the comport structure |
| | | * Input Args: dev_name: The comport device name path, such as '/dev/ttyS3' |
| | | * baudrate: The baudrate, such as 115200 |
| | | * settings: The databit,parity,stopbit,flowctrl settings, such as '8N1N' |
| | | * Output Args: NONE |
| | | * Return Value: The COM_PORT structure pointer. |
| | | *************************************************************************************/ |
| | | COM_PORT *comport_init(const char *dev_name, int baudrate, const char *settings) |
| | | { |
| | | COM_PORT *comport = NULL; |
| | | if (NULL == (comport = (COM_PORT *) malloc(sizeof(COM_PORT)))) |
| | | { |
| | | return NULL; |
| | | } |
| | | memset(comport, 0, sizeof(COM_PORT)); |
| | | comport->is_connted = 0; |
| | | comport->frag_size = 128; |
| | | |
| | | strncpy(comport->dev_name, dev_name, DEVNAME_LEN); |
| | | comport->baudrate = baudrate; |
| | | |
| | | set_settings(comport, settings); |
| | | #ifdef COM_DEBUG |
| | | disp_settings(comport); |
| | | #endif |
| | | |
| | | return comport; |
| | | } |
| | | |
| | | #ifdef COM_DEBUG |
| | | void disp_settings(COM_PORT * comport) |
| | | { |
| | | COM_PRINT("Device:\t\t\t\"%s\"\n", comport->dev_name); |
| | | COM_PRINT("Baudrate:\t\t%ld\n", comport->baudrate); |
| | | COM_PRINT("DataBit:\t\t\'%d\'\n", comport->databit); |
| | | switch (comport->parity) |
| | | { |
| | | case 0: |
| | | COM_PRINT("Parity:\t\t\t\'N\'\n"); |
| | | break; |
| | | case 1: |
| | | COM_PRINT("Parity:\t\t\t\'O\'\n"); |
| | | break; |
| | | case 2: |
| | | COM_PRINT("Parity:\t\t\t\'E\'\n"); |
| | | break; |
| | | case 3: |
| | | COM_PRINT("Parity:\t\t\t\'S\'\n"); |
| | | break; |
| | | } |
| | | COM_PRINT("StopBit:\t\t\'%ld\'\n", (long int)comport->stopbit); |
| | | switch (comport->flowctrl) |
| | | { |
| | | case 0: |
| | | COM_PRINT("FlowCtrl:\t\t\'N\'\n"); |
| | | break; |
| | | case 1: |
| | | COM_PRINT("FlowCtrl:\t\t\'S\'\n"); |
| | | break; |
| | | case 2: |
| | | COM_PRINT("FlowCtrl:\t\t\'H\'\n"); |
| | | break; |
| | | case 3: |
| | | COM_PRINT("FlowCtrl:\t\t\'B\'\n"); |
| | | break; |
| | | } |
| | | COM_PRINT("\n"); |
| | | return; |
| | | } |
| | | #endif |
| | | |
| | | /************************************************************************************** |
| | | * Description: Set the comport databit,parity,stopbit,flowctrl |
| | | * Input Args: comport: the COM_PORT pointer |
| | | * settings: The databit/parity/stopbit/flowctrl settings as like "8N1N" |
| | | * Output Args: NONE |
| | | * Return Value: NONE |
| | | *************************************************************************************/ |
| | | void set_settings(COM_PORT * comport, const char *settings) |
| | | { |
| | | if(NULL==settings || NULL==comport) |
| | | return ; |
| | | |
| | | switch (settings[0]) /* data bit */ |
| | | { |
| | | case '7': |
| | | comport->databit = 7; |
| | | break; |
| | | case '8': |
| | | default: |
| | | comport->databit = 8; |
| | | break; |
| | | } |
| | | |
| | | switch (settings[1]) /* parity */ |
| | | { |
| | | case 'O': |
| | | case 'o': |
| | | comport->parity = 1; |
| | | break; |
| | | case 'E': |
| | | case 'e': |
| | | comport->parity = 2; |
| | | break; |
| | | case 'S': |
| | | case 's': |
| | | comport->parity = 3; |
| | | break; |
| | | case 'N': |
| | | case 'n': |
| | | default: |
| | | comport->parity = 0; |
| | | break; |
| | | } |
| | | |
| | | switch (settings[2]) /* stop bit */ |
| | | { |
| | | case '0': |
| | | comport->stopbit = 0; |
| | | break; |
| | | case '1': |
| | | default: |
| | | comport->stopbit = 1; |
| | | break; |
| | | } |
| | | |
| | | switch (settings[3]) /* flow control */ |
| | | { |
| | | case 'S': |
| | | case 's': |
| | | comport->flowctrl = 1; |
| | | break; |
| | | case 'H': |
| | | case 'h': |
| | | comport->flowctrl = 2; |
| | | break; |
| | | case 'B': |
| | | case 'b': |
| | | comport->flowctrl = 3; |
| | | break; |
| | | case 'N': |
| | | case 'n': |
| | | default: |
| | | comport->flowctrl = 0; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | void comport_close(COM_PORT * comport) |
| | | { |
| | | if (0 != comport->fd) |
| | | { |
| | | COM_PRINT("Close device \"%s\"\n", comport->dev_name); |
| | | close(comport->fd); |
| | | } |
| | | comport->is_connted = 0x00; |
| | | comport->fd = -1; |
| | | } |
| | | |
| | | void comport_term(COM_PORT * comport) |
| | | { |
| | | if(NULL == comport) |
| | | return; |
| | | |
| | | if (0 != comport->fd) |
| | | { |
| | | comport_close(comport); |
| | | } |
| | | memset(comport, 0x00, sizeof(COM_PORT)); |
| | | free(comport); |
| | | comport = NULL; |
| | | |
| | | return; |
| | | } |
| | | |
| | | int comport_open(COM_PORT * comport) |
| | | { |
| | | int retval = -1; |
| | | struct termios old_cfg, new_cfg; |
| | | int old_flags; |
| | | long tmp; |
| | | |
| | | if(NULL==comport) |
| | | return -1; |
| | | |
| | | comport_close(comport); |
| | | |
| | | |
| | | /* Not a TTY device */ |
| | | if( !strstr(comport->dev_name, "tty")) |
| | | { |
| | | COM_PRINT("Open Not tty device \"%s\"\n", comport->dev_name); |
| | | comport->fd = open(comport->dev_name, O_RDWR); |
| | | retval = comport->fd<0 ? -2 : comport->fd; |
| | | goto CleanUp; |
| | | } |
| | | |
| | | comport->fd = open(comport->dev_name, O_RDWR | O_NOCTTY | O_NONBLOCK); |
| | | if (comport->fd < 0) |
| | | { |
| | | retval = -3; |
| | | goto CleanUp; |
| | | } |
| | | COM_PRINT("Open device \"%s\"\n", comport->dev_name); |
| | | |
| | | if ((-1 != (old_flags = fcntl(comport->fd, F_GETFL, 0))) |
| | | && (-1 != fcntl(comport->fd, F_SETFL, old_flags & ~O_NONBLOCK))) |
| | | { |
| | | // Flush input and output |
| | | if (-1 == tcflush(comport->fd, TCIOFLUSH)) |
| | | { |
| | | retval = -4; |
| | | goto CleanUp; |
| | | } |
| | | } |
| | | else // Failure |
| | | { |
| | | retval = -5; |
| | | goto CleanUp; |
| | | } |
| | | |
| | | if (0 != tcgetattr(comport->fd, &old_cfg)) |
| | | { |
| | | retval = -6; // Failed to get Com settings |
| | | goto CleanUp; |
| | | } |
| | | |
| | | memset(&new_cfg, 0, sizeof(new_cfg)); |
| | | |
| | | /*=====================================*/ |
| | | /* Configure comport */ |
| | | /*=====================================*/ |
| | | |
| | | new_cfg.c_cflag &= ~CSIZE; |
| | | new_cfg.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); |
| | | new_cfg.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); |
| | | new_cfg.c_oflag &= ~(OPOST); |
| | | |
| | | /* Set the data bit */ |
| | | switch (comport->databit) |
| | | { |
| | | case 0x07: |
| | | new_cfg.c_cflag |= CS7; |
| | | break; |
| | | case 0x06: |
| | | new_cfg.c_cflag |= CS6; |
| | | break; |
| | | case 0x05: |
| | | new_cfg.c_cflag |= CS5; |
| | | break; |
| | | default: |
| | | new_cfg.c_cflag |= CS8; |
| | | break; |
| | | } |
| | | |
| | | /* Set the parity */ |
| | | switch (comport->parity) |
| | | { |
| | | case 0x01: // Odd |
| | | new_cfg.c_cflag |= (PARENB | PARODD); |
| | | new_cfg.c_cflag |= (INPCK | ISTRIP); |
| | | break; |
| | | case 0x02: // Even |
| | | new_cfg.c_cflag |= PARENB; |
| | | new_cfg.c_cflag &= ~PARODD;; |
| | | new_cfg.c_cflag |= (INPCK | ISTRIP); |
| | | break; |
| | | case 0x03: |
| | | new_cfg.c_cflag &= ~PARENB; |
| | | new_cfg.c_cflag &= ~CSTOPB; |
| | | break; |
| | | default: |
| | | new_cfg.c_cflag &= ~PARENB; |
| | | } |
| | | |
| | | /* Set Stop bit */ |
| | | if (0x01 != comport->stopbit) |
| | | { |
| | | new_cfg.c_cflag |= CSTOPB; |
| | | } |
| | | else |
| | | { |
| | | new_cfg.c_cflag &= ~CSTOPB; |
| | | } |
| | | |
| | | /* Set flow control */ |
| | | switch (comport->flowctrl) |
| | | { |
| | | case 1: // Software control |
| | | case 3: |
| | | new_cfg.c_cflag &= ~(CRTSCTS); |
| | | new_cfg.c_iflag |= (IXON | IXOFF); |
| | | break; |
| | | case 2: // Hardware control |
| | | new_cfg.c_cflag |= CRTSCTS; // Also called CRTSCTS |
| | | new_cfg.c_iflag &= ~(IXON | IXOFF); |
| | | break; |
| | | default: // NONE |
| | | new_cfg.c_cflag &= ~(CRTSCTS); |
| | | new_cfg.c_iflag &= ~(IXON | IXOFF); |
| | | break; |
| | | } |
| | | |
| | | /* Set baudrate */ |
| | | switch (comport->baudrate) |
| | | { |
| | | case 115200: |
| | | tmp = B115200; |
| | | break; |
| | | case 57600: |
| | | tmp = B57600; |
| | | break; |
| | | case 38400: |
| | | tmp = B38400; |
| | | break; |
| | | case 19200: |
| | | tmp = B19200; |
| | | break; |
| | | case 9600: |
| | | tmp = B9600; |
| | | break; |
| | | case 4800: |
| | | tmp = B4800; |
| | | break; |
| | | case 2400: |
| | | tmp = B2400; |
| | | break; |
| | | case 1800: |
| | | tmp = B1800; |
| | | break; |
| | | case 1200: |
| | | tmp = B1200; |
| | | break; |
| | | case 600: |
| | | tmp = B600; |
| | | break; |
| | | case 300: |
| | | tmp = B300; |
| | | break; |
| | | case 200: |
| | | tmp = B200; |
| | | break; |
| | | case 150: |
| | | tmp = B150; |
| | | break; |
| | | case 134: |
| | | tmp = B134; |
| | | break; |
| | | case 110: |
| | | tmp = B110; |
| | | break; |
| | | case 75: |
| | | tmp = B75; |
| | | break; |
| | | case 50: |
| | | tmp = B50; |
| | | break; |
| | | default: |
| | | tmp = B115200; |
| | | } |
| | | cfsetispeed(&new_cfg, tmp); |
| | | cfsetispeed(&new_cfg, tmp); |
| | | |
| | | /* Set the Com port timeout settings */ |
| | | new_cfg.c_cc[VMIN] = 0; |
| | | new_cfg.c_cc[VTIME] = 0; |
| | | |
| | | tcflush(comport->fd, TCIFLUSH); |
| | | if (0 != tcsetattr(comport->fd, TCSANOW, &new_cfg)) |
| | | { |
| | | retval = -7; // Failed to set device com port settings |
| | | goto CleanUp; |
| | | } |
| | | |
| | | COM_PRINT("Connected device \"%s\".\n", comport->dev_name); |
| | | comport->is_connted = 0x01; |
| | | retval = comport->fd; |
| | | |
| | | CleanUp: |
| | | COM_PRINT("Open device \"%s\" %s.\n", comport->dev_name, retval>0 ? "successfully" : "failure"); |
| | | return retval; |
| | | } |
| | | |
| | | void nonblock() |
| | | { |
| | | struct termios ttystate; |
| | | |
| | | //get the terminal state |
| | | tcgetattr(STDIN_FILENO, &ttystate); |
| | | |
| | | //turn off canonical mode |
| | | ttystate.c_lflag &= ~ICANON; |
| | | //minimum of number input read. |
| | | ttystate.c_cc[VMIN] = 1; |
| | | |
| | | //set the terminal attributes. |
| | | tcsetattr(STDIN_FILENO, TCSANOW, &ttystate); |
| | | } |
| | | |
| | | int kbhit() |
| | | { |
| | | struct timeval tv; |
| | | fd_set fds; |
| | | tv.tv_sec = 0; |
| | | tv.tv_usec = 0; |
| | | FD_ZERO(&fds); |
| | | FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0 |
| | | select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv); |
| | | return FD_ISSET(STDIN_FILENO, &fds); |
| | | } |
| | | |
| | | int comport_recv(COM_PORT * comport, char *buf, int buf_size, unsigned long timeout) |
| | | { |
| | | int retval = 0; // Function return value |
| | | int iRet; |
| | | fd_set stReadFds, stExcpFds; |
| | | struct timeval stTime; |
| | | |
| | | if (NULL == buf || 0 >= buf_size) |
| | | { |
| | | COM_PRINT("%s() usage error.\n", __FUNCTION__); |
| | | retval = -1; |
| | | goto CleanUp; |
| | | } |
| | | |
| | | if (0x01 != comport->is_connted) |
| | | { |
| | | COM_PRINT("%s() comport not connected.\n", __FUNCTION__); |
| | | retval = -2; |
| | | goto CleanUp; |
| | | } |
| | | |
| | | //printf("bufsize=%d timeout=%lu\n", buf_size, timeout); |
| | | |
| | | FD_ZERO(&stReadFds); |
| | | FD_ZERO(&stExcpFds); |
| | | FD_SET(comport->fd, &stReadFds); |
| | | FD_SET(comport->fd, &stExcpFds); |
| | | |
| | | if (0xFFFFFFFF != timeout) |
| | | { |
| | | stTime.tv_sec = (time_t) (timeout / 1000); |
| | | stTime.tv_usec = (long)(1000 * (timeout % 1000)); |
| | | |
| | | iRet = select(comport->fd + 1, &stReadFds, 0, &stExcpFds, &stTime); |
| | | if (0 == iRet) |
| | | { |
| | | retval = 0; // No data in Com port buffer |
| | | goto CleanUp; |
| | | } |
| | | else if (0 < iRet) |
| | | { |
| | | if (0 != FD_ISSET(comport->fd, &stExcpFds)) |
| | | { |
| | | retval = -6; // Error during checking recv status |
| | | COM_PRINT("Error checking recv status.\n"); |
| | | goto CleanUp; |
| | | } |
| | | |
| | | if (0 == FD_ISSET(comport->fd, &stReadFds)) |
| | | { |
| | | retval = 0; // No incoming data |
| | | COM_PRINT("No incoming data.\n"); |
| | | goto CleanUp; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | if (EINTR == errno) |
| | | { |
| | | COM_PRINT("catch interrupt signal.\n"); |
| | | retval = 0; // Interrupted signal catched |
| | | } |
| | | else |
| | | { |
| | | COM_PRINT("Check recv status failure.\n"); |
| | | retval = -7; // Error during checking recv status |
| | | } |
| | | |
| | | goto CleanUp; |
| | | } |
| | | } |
| | | |
| | | usleep(10000); /* sleep for 10ms for data incoming */ |
| | | |
| | | // Get data from Com port |
| | | iRet = read(comport->fd, buf, buf_size); |
| | | if (0 > iRet) |
| | | { |
| | | if (EINTR == errno) |
| | | retval = 0; // Interrupted signal catched |
| | | else |
| | | retval = -3; // Failed to read Com port |
| | | |
| | | goto CleanUp; |
| | | } |
| | | |
| | | #if 0 |
| | | { |
| | | int i=0; |
| | | printf("Receive %d bytes data: \n", iRet); |
| | | for(i=0; i<iRet; i++) |
| | | { |
| | | printf("0x%02x ", buf[i]); |
| | | } |
| | | printf("\n"); |
| | | } |
| | | #endif |
| | | |
| | | retval = iRet; |
| | | |
| | | CleanUp: |
| | | return retval; |
| | | |
| | | } |
| | | |
| | | int comport_send(COM_PORT * comport, char *buf, int send_bytes) |
| | | { |
| | | char *ptr, *end; |
| | | int retval = 0; |
| | | int send = 0; |
| | | |
| | | if (NULL == buf || 0 >= send_bytes) |
| | | { |
| | | COM_PRINT("%s() Usage error.\n", __FUNCTION__); |
| | | retval = -1; |
| | | goto CleanUp; |
| | | } |
| | | |
| | | if (0x01 != comport->is_connted) // Comport not opened ? |
| | | { |
| | | retval = -3; |
| | | COM_PRINT("Serail not connected.\n"); |
| | | goto CleanUp; |
| | | } |
| | | |
| | | //printf("Send %s with %d bytes.\n", buf, send_bytes); |
| | | |
| | | // Large data, then slice them and send |
| | | if (comport->frag_size < send_bytes) |
| | | { |
| | | ptr = buf; |
| | | end = buf + send_bytes; |
| | | |
| | | do |
| | | { |
| | | // Large than frag_size |
| | | if (comport->frag_size < (end - ptr)) |
| | | { |
| | | send = write(comport->fd, ptr, comport->frag_size); |
| | | if (0 >= send || comport->frag_size != send) |
| | | { |
| | | retval = -4; |
| | | goto CleanUp; |
| | | } |
| | | ptr += comport->frag_size; |
| | | } |
| | | else // Less than frag_size, maybe last fragmention. |
| | | { |
| | | send = write(comport->fd, ptr, (end - ptr)); |
| | | if (0 >= send || (end - ptr) != send) |
| | | { |
| | | retval = -4; |
| | | goto CleanUp; |
| | | } |
| | | ptr += (end - ptr); |
| | | } |
| | | } |
| | | while (ptr < end); |
| | | } |
| | | else // The send data is not large than a fragmention. |
| | | { |
| | | send = write(comport->fd, buf, send_bytes); |
| | | if (0 >= send || send_bytes != send) |
| | | { |
| | | retval = -5; |
| | | goto CleanUp; |
| | | } |
| | | } |
| | | |
| | | CleanUp: |
| | | return retval; |
| | | } |
| | | |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue <guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_comport.h |
| | | * Description: This head file is for the common TTY/Serial port operator library |
| | | * |
| | | * Version: 1.0.0(10/17/2011~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "10/17/2011 03:33:25 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | #ifndef _CP_COMPORT_H |
| | | #define _CP_COMPORT_H |
| | | |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <unistd.h> |
| | | #include <string.h> |
| | | #include <getopt.h> |
| | | #include <fcntl.h> |
| | | #include <errno.h> |
| | | #include <termios.h> |
| | | #include <sys/stat.h> |
| | | #include <sys/wait.h> |
| | | #include <sys/types.h> |
| | | #include <sys/stat.h> |
| | | #include <sys/select.h> |
| | | |
| | | #define BUF_64 64 |
| | | |
| | | #ifndef DEVNAME_LEN |
| | | #define DEVNAME_LEN 64 |
| | | #endif |
| | | |
| | | //#define COM_DEBUG |
| | | #ifdef COM_DEBUG |
| | | #define COM_PRINT(format,args...) printf(format, ##args) |
| | | #else |
| | | #define COM_PRINT(format,args...) do{} while(0); |
| | | #endif |
| | | |
| | | //#define msleep(m) {struct timespec cSleep; cSleep.tv_sec = 0; cSleep.tv_nsec = m * 1000; nanosleep(&cSleep, 0);} |
| | | |
| | | typedef struct __COM_PORT |
| | | { |
| | | unsigned char databit, parity, stopbit, flowctrl, is_connted; |
| | | char dev_name[DEVNAME_LEN]; |
| | | unsigned char used; /* This comport used or not now */ |
| | | int fd; |
| | | int frag_size; |
| | | long baudrate; |
| | | } COM_PORT; |
| | | |
| | | COM_PORT *comport_init(const char *dev_name, int baudrate, const char *settings); |
| | | void comport_close(COM_PORT * comport); |
| | | int comport_open(COM_PORT * comport); |
| | | void comport_term(COM_PORT * comport); |
| | | int comport_recv(COM_PORT * comport, char *buf, int buf_size, unsigned long timeout); |
| | | int comport_send(COM_PORT * comport, char *buf, int send_bytes); |
| | | |
| | | void set_settings(COM_PORT * comport, const char *settings); |
| | | void disp_settings(COM_PORT * comport); |
| | | void nonblock(); |
| | | int kbhit(); |
| | | |
| | | #endif |
New file |
| | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @file cp_dictionary.c |
| | | @author N. Devillard |
| | | @brief Implements a dictionary for string variables. |
| | | |
| | | This module implements a simple dictionary object, i.e. a list |
| | | of string/string associations. This object is useful to store e.g. |
| | | informations retrieved from a configuration file (ini files). |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | |
| | | /*--------------------------------------------------------------------------- |
| | | Includes |
| | | ---------------------------------------------------------------------------*/ |
| | | #include "cp_dictionary.h" |
| | | |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <string.h> |
| | | #include <unistd.h> |
| | | |
| | | /** Maximum value size for integers and doubles. */ |
| | | #define MAXVALSZ 1024 |
| | | |
| | | /** Minimal allocated number of entries in a dictionary */ |
| | | #define DICTMINSZ 128 |
| | | |
| | | /** Invalid key token */ |
| | | #define DICT_INVALID_KEY ((char*)-1) |
| | | |
| | | /*--------------------------------------------------------------------------- |
| | | Private functions |
| | | ---------------------------------------------------------------------------*/ |
| | | |
| | | /* Doubles the allocated size associated to a pointer */ |
| | | /* 'size' is the current allocated size. */ |
| | | static void * mem_double(void * ptr, int size) |
| | | { |
| | | void * newptr ; |
| | | |
| | | newptr = calloc(2*size, 1); |
| | | if (newptr==NULL) { |
| | | return NULL ; |
| | | } |
| | | memcpy(newptr, ptr, size); |
| | | free(ptr); |
| | | return newptr ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Duplicate a string |
| | | @param s String to duplicate |
| | | @return Pointer to a newly allocated string, to be freed with free() |
| | | |
| | | This is a replacement for strdup(). This implementation is provided |
| | | for systems that do not have it. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | static char * xstrdup(const char * s) |
| | | { |
| | | char * t ; |
| | | if (!s) |
| | | return NULL ; |
| | | t = (char*)malloc(strlen(s)+1) ; |
| | | if (t) { |
| | | strcpy(t,s); |
| | | } |
| | | return t ; |
| | | } |
| | | |
| | | /*--------------------------------------------------------------------------- |
| | | Function codes |
| | | ---------------------------------------------------------------------------*/ |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Compute the hash key for a string. |
| | | @param key Character string to use for key. |
| | | @return 1 unsigned int on at least 32 bits. |
| | | |
| | | This hash function has been taken from an Article in Dr Dobbs Journal. |
| | | This is normally a collision-free function, distributing keys evenly. |
| | | The key is stored anyway in the struct so that collision can be avoided |
| | | by comparing the key itself in last resort. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | unsigned dictionary_hash(const char * key) |
| | | { |
| | | int len ; |
| | | unsigned hash ; |
| | | int i ; |
| | | |
| | | len = strlen(key); |
| | | for (hash=0, i=0 ; i<len ; i++) { |
| | | hash += (unsigned)key[i] ; |
| | | hash += (hash<<10); |
| | | hash ^= (hash>>6) ; |
| | | } |
| | | hash += (hash <<3); |
| | | hash ^= (hash >>11); |
| | | hash += (hash <<15); |
| | | return hash ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Create a new dictionary object. |
| | | @param size Optional initial size of the dictionary. |
| | | @return 1 newly allocated dictionary objet. |
| | | |
| | | This function allocates a new dictionary object of given size and returns |
| | | it. If you do not know in advance (roughly) the number of entries in the |
| | | dictionary, give size=0. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | dictionary * dictionary_new(int size) |
| | | { |
| | | dictionary * d ; |
| | | |
| | | /* If no size was specified, allocate space for DICTMINSZ */ |
| | | if (size<DICTMINSZ) size=DICTMINSZ ; |
| | | |
| | | if (!(d = (dictionary *)calloc(1, sizeof(dictionary)))) { |
| | | return NULL; |
| | | } |
| | | d->size = size ; |
| | | d->val = (char **)calloc(size, sizeof(char*)); |
| | | d->key = (char **)calloc(size, sizeof(char*)); |
| | | d->hash = (unsigned int *)calloc(size, sizeof(unsigned)); |
| | | return d ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Delete a dictionary object |
| | | @param d dictionary object to deallocate. |
| | | @return void |
| | | |
| | | Deallocate a dictionary object and all memory associated to it. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void dictionary_del(dictionary * d) |
| | | { |
| | | int i ; |
| | | |
| | | if (d==NULL) return ; |
| | | for (i=0 ; i<d->size ; i++) { |
| | | if (d->key[i]!=NULL) |
| | | free(d->key[i]); |
| | | if (d->val[i]!=NULL) |
| | | free(d->val[i]); |
| | | } |
| | | free(d->val); |
| | | free(d->key); |
| | | free(d->hash); |
| | | free(d); |
| | | return ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get a value from a dictionary. |
| | | @param d dictionary object to search. |
| | | @param key Key to look for in the dictionary. |
| | | @param def Default value to return if key not found. |
| | | @return 1 pointer to internally allocated character string. |
| | | |
| | | This function locates a key in a dictionary and returns a pointer to its |
| | | value, or the passed 'def' pointer if no such key can be found in |
| | | dictionary. The returned character pointer points to data internal to the |
| | | dictionary object, you should not try to free it or modify it. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | char * dictionary_get(dictionary * d, const char * key, char * def) |
| | | { |
| | | unsigned hash ; |
| | | int i ; |
| | | |
| | | hash = dictionary_hash(key); |
| | | for (i=0 ; i<d->size ; i++) { |
| | | if (d->key[i]==NULL) |
| | | continue ; |
| | | /* Compare hash */ |
| | | if (hash==d->hash[i]) { |
| | | /* Compare string, to avoid hash collisions */ |
| | | if (!strcmp(key, d->key[i])) { |
| | | return d->val[i] ; |
| | | } |
| | | } |
| | | } |
| | | return def ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Set a value in a dictionary. |
| | | @param d dictionary object to modify. |
| | | @param key Key to modify or add. |
| | | @param val Value to add. |
| | | @return int 0 if Ok, anything else otherwise |
| | | |
| | | If the given key is found in the dictionary, the associated value is |
| | | replaced by the provided one. If the key cannot be found in the |
| | | dictionary, it is added to it. |
| | | |
| | | It is Ok to provide a NULL value for val, but NULL values for the dictionary |
| | | or the key are considered as errors: the function will return immediately |
| | | in such a case. |
| | | |
| | | Notice that if you dictionary_set a variable to NULL, a call to |
| | | dictionary_get will return a NULL value: the variable will be found, and |
| | | its value (NULL) is returned. In other words, setting the variable |
| | | content to NULL is equivalent to deleting the variable from the |
| | | dictionary. It is not possible (in this implementation) to have a key in |
| | | the dictionary without value. |
| | | |
| | | This function returns non-zero in case of failure. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int dictionary_set(dictionary * d, const char * key, const char * val) |
| | | { |
| | | int i ; |
| | | unsigned hash ; |
| | | |
| | | if (d==NULL || key==NULL) return -1 ; |
| | | |
| | | /* Compute hash for this key */ |
| | | hash = dictionary_hash(key) ; |
| | | /* Find if value is already in dictionary */ |
| | | if (d->n>0) { |
| | | for (i=0 ; i<d->size ; i++) { |
| | | if (d->key[i]==NULL) |
| | | continue ; |
| | | if (hash==d->hash[i]) { /* Same hash value */ |
| | | if (!strcmp(key, d->key[i])) { /* Same key */ |
| | | /* Found a value: modify and return */ |
| | | if (d->val[i]!=NULL) |
| | | free(d->val[i]); |
| | | d->val[i] = val ? xstrdup(val) : NULL ; |
| | | /* Value has been modified: return */ |
| | | return 0 ; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | /* Add a new value */ |
| | | /* See if dictionary needs to grow */ |
| | | if (d->n==d->size) { |
| | | |
| | | /* Reached maximum size: reallocate dictionary */ |
| | | d->val = (char **)mem_double(d->val, d->size * sizeof(char*)) ; |
| | | d->key = (char **)mem_double(d->key, d->size * sizeof(char*)) ; |
| | | d->hash = (unsigned int *)mem_double(d->hash, d->size * sizeof(unsigned)) ; |
| | | if ((d->val==NULL) || (d->key==NULL) || (d->hash==NULL)) { |
| | | /* Cannot grow dictionary */ |
| | | return -1 ; |
| | | } |
| | | /* Double size */ |
| | | d->size *= 2 ; |
| | | } |
| | | |
| | | /* Insert key in the first empty slot. Start at d->n and wrap at |
| | | d->size. Because d->n < d->size this will necessarily |
| | | terminate. */ |
| | | for (i=d->n ; d->key[i] ; ) { |
| | | if(++i == d->size) i = 0; |
| | | } |
| | | /* Copy key */ |
| | | d->key[i] = xstrdup(key); |
| | | d->val[i] = val ? xstrdup(val) : NULL ; |
| | | d->hash[i] = hash; |
| | | d->n ++ ; |
| | | return 0 ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Delete a key in a dictionary |
| | | @param d dictionary object to modify. |
| | | @param key Key to remove. |
| | | @return void |
| | | |
| | | This function deletes a key in a dictionary. Nothing is done if the |
| | | key cannot be found. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void dictionary_unset(dictionary * d, const char * key) |
| | | { |
| | | unsigned hash ; |
| | | int i ; |
| | | |
| | | if (key == NULL) { |
| | | return; |
| | | } |
| | | |
| | | hash = dictionary_hash(key); |
| | | for (i=0 ; i<d->size ; i++) { |
| | | if (d->key[i]==NULL) |
| | | continue ; |
| | | /* Compare hash */ |
| | | if (hash==d->hash[i]) { |
| | | /* Compare string, to avoid hash collisions */ |
| | | if (!strcmp(key, d->key[i])) { |
| | | /* Found key */ |
| | | break ; |
| | | } |
| | | } |
| | | } |
| | | if (i>=d->size) |
| | | /* Key not found */ |
| | | return ; |
| | | |
| | | free(d->key[i]); |
| | | d->key[i] = NULL ; |
| | | if (d->val[i]!=NULL) { |
| | | free(d->val[i]); |
| | | d->val[i] = NULL ; |
| | | } |
| | | d->hash[i] = 0 ; |
| | | d->n -- ; |
| | | return ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Dump a dictionary to an opened file pointer. |
| | | @param d Dictionary to dump |
| | | @param f Opened file pointer. |
| | | @return void |
| | | |
| | | Dumps a dictionary onto an opened file pointer. Key pairs are printed out |
| | | as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as |
| | | output file pointers. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void dictionary_dump(dictionary * d, FILE * out) |
| | | { |
| | | int i ; |
| | | |
| | | if (d==NULL || out==NULL) return ; |
| | | if (d->n<1) { |
| | | fprintf(out, "empty dictionary\n"); |
| | | return ; |
| | | } |
| | | for (i=0 ; i<d->size ; i++) { |
| | | if (d->key[i]) { |
| | | fprintf(out, "%20s\t[%s]\n", |
| | | d->key[i], |
| | | d->val[i] ? d->val[i] : "UNDEF"); |
| | | } |
| | | } |
| | | return ; |
| | | } |
| | | |
| | | |
| | | /* Test code */ |
| | | #ifdef TESTDIC |
| | | #define NVALS 20000 |
| | | int main(int argc, char *argv[]) |
| | | { |
| | | dictionary * d ; |
| | | char * val ; |
| | | int i ; |
| | | char cval[90] ; |
| | | |
| | | /* Allocate dictionary */ |
| | | printf("allocating...\n"); |
| | | d = dictionary_new(0); |
| | | |
| | | /* Set values in dictionary */ |
| | | printf("setting %d values...\n", NVALS); |
| | | for (i=0 ; i<NVALS ; i++) { |
| | | sprintf(cval, "%04d", i); |
| | | dictionary_set(d, cval, "salut"); |
| | | } |
| | | printf("getting %d values...\n", NVALS); |
| | | for (i=0 ; i<NVALS ; i++) { |
| | | sprintf(cval, "%04d", i); |
| | | val = dictionary_get(d, cval, DICT_INVALID_KEY); |
| | | if (val==DICT_INVALID_KEY) { |
| | | printf("cannot get value for key [%s]\n", cval); |
| | | } |
| | | } |
| | | printf("unsetting %d values...\n", NVALS); |
| | | for (i=0 ; i<NVALS ; i++) { |
| | | sprintf(cval, "%04d", i); |
| | | dictionary_unset(d, cval); |
| | | } |
| | | if (d->n != 0) { |
| | | printf("error deleting values\n"); |
| | | } |
| | | printf("deallocating...\n"); |
| | | dictionary_del(d); |
| | | return 0 ; |
| | | } |
| | | #endif |
| | | /* vim: set ts=4 et sw=4 tw=75 */ |
New file |
| | |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @file cp_dictionary.h |
| | | @author N. Devillard |
| | | @brief Implements a dictionary for string variables. |
| | | |
| | | This module implements a simple dictionary object, i.e. a list |
| | | of string/string associations. This object is useful to store e.g. |
| | | informations retrieved from a configuration file (ini files). |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | |
| | | #ifndef _CP_DICTIONARY_H_ |
| | | #define _CP_DICTIONARY_H_ |
| | | |
| | | /*--------------------------------------------------------------------------- |
| | | Includes |
| | | ---------------------------------------------------------------------------*/ |
| | | |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <string.h> |
| | | #include <unistd.h> |
| | | |
| | | /*--------------------------------------------------------------------------- |
| | | New types |
| | | ---------------------------------------------------------------------------*/ |
| | | |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Dictionary object |
| | | |
| | | This object contains a list of string/string associations. Each |
| | | association is identified by a unique string key. Looking up values |
| | | in the dictionary is speeded up by the use of a (hopefully collision-free) |
| | | hash function. |
| | | */ |
| | | /*-------------------------------------------------------------------------*/ |
| | | typedef struct _dictionary_ { |
| | | int n ; /** Number of entries in dictionary */ |
| | | int size ; /** Storage size */ |
| | | char ** val ; /** List of string values */ |
| | | char ** key ; /** List of string keys */ |
| | | unsigned * hash ; /** List of hash values for keys */ |
| | | } dictionary ; |
| | | |
| | | |
| | | /*--------------------------------------------------------------------------- |
| | | Function prototypes |
| | | ---------------------------------------------------------------------------*/ |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Compute the hash key for a string. |
| | | @param key Character string to use for key. |
| | | @return 1 unsigned int on at least 32 bits. |
| | | |
| | | This hash function has been taken from an Article in Dr Dobbs Journal. |
| | | This is normally a collision-free function, distributing keys evenly. |
| | | The key is stored anyway in the struct so that collision can be avoided |
| | | by comparing the key itself in last resort. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | unsigned dictionary_hash(const char * key); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Create a new dictionary object. |
| | | @param size Optional initial size of the dictionary. |
| | | @return 1 newly allocated dictionary objet. |
| | | |
| | | This function allocates a new dictionary object of given size and returns |
| | | it. If you do not know in advance (roughly) the number of entries in the |
| | | dictionary, give size=0. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | dictionary * dictionary_new(int size); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Delete a dictionary object |
| | | @param d dictionary object to deallocate. |
| | | @return void |
| | | |
| | | Deallocate a dictionary object and all memory associated to it. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void dictionary_del(dictionary * vd); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get a value from a dictionary. |
| | | @param d dictionary object to search. |
| | | @param key Key to look for in the dictionary. |
| | | @param def Default value to return if key not found. |
| | | @return 1 pointer to internally allocated character string. |
| | | |
| | | This function locates a key in a dictionary and returns a pointer to its |
| | | value, or the passed 'def' pointer if no such key can be found in |
| | | dictionary. The returned character pointer points to data internal to the |
| | | dictionary object, you should not try to free it or modify it. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | char * dictionary_get(dictionary * d, const char * key, char * def); |
| | | |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Set a value in a dictionary. |
| | | @param d dictionary object to modify. |
| | | @param key Key to modify or add. |
| | | @param val Value to add. |
| | | @return int 0 if Ok, anything else otherwise |
| | | |
| | | If the given key is found in the dictionary, the associated value is |
| | | replaced by the provided one. If the key cannot be found in the |
| | | dictionary, it is added to it. |
| | | |
| | | It is Ok to provide a NULL value for val, but NULL values for the dictionary |
| | | or the key are considered as errors: the function will return immediately |
| | | in such a case. |
| | | |
| | | Notice that if you dictionary_set a variable to NULL, a call to |
| | | dictionary_get will return a NULL value: the variable will be found, and |
| | | its value (NULL) is returned. In other words, setting the variable |
| | | content to NULL is equivalent to deleting the variable from the |
| | | dictionary. It is not possible (in this implementation) to have a key in |
| | | the dictionary without value. |
| | | |
| | | This function returns non-zero in case of failure. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int dictionary_set(dictionary * vd, const char * key, const char * val); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Delete a key in a dictionary |
| | | @param d dictionary object to modify. |
| | | @param key Key to remove. |
| | | @return void |
| | | |
| | | This function deletes a key in a dictionary. Nothing is done if the |
| | | key cannot be found. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void dictionary_unset(dictionary * d, const char * key); |
| | | |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Dump a dictionary to an opened file pointer. |
| | | @param d Dictionary to dump |
| | | @param f Opened file pointer. |
| | | @return void |
| | | |
| | | Dumps a dictionary onto an opened file pointer. Key pairs are printed out |
| | | as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as |
| | | output file pointers. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void dictionary_dump(dictionary * d, FILE * out); |
| | | |
| | | #endif |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_fds.c |
| | | * Description: This file is the linux epoll basic library |
| | | * |
| | | * Version: 1.0.0(10/25/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "10/25/2012 04:55:30 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include <sys/resource.h> |
| | | #include "cp_fds.h" |
| | | #include "cp_sock.h" |
| | | #include "cp_time.h" |
| | | #include "cp_common.h" |
| | | |
| | | /* set maximum file descriptor number that can be opened in this process */ |
| | | int cp_fds_setrlimit(int maxfd) |
| | | { |
| | | struct rlimit res; |
| | | |
| | | if(getrlimit(RLIMIT_NOFILE, &res) <0) |
| | | { |
| | | log_fatal("getrlimit failed: %s\n", strerror(errno)); |
| | | return -1; |
| | | } |
| | | |
| | | if(res.rlim_cur < maxfd) |
| | | { |
| | | res.rlim_cur = maxfd; |
| | | if(setrlimit(RLIMIT_NOFILE, &res) <0) |
| | | { |
| | | log_fatal("setrlimit failed: %s\n", strerror(errno)); |
| | | return -2; |
| | | } |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | /* Initialze $fds context, if $fds is NULL, then malloc it */ |
| | | CP_FDS *cp_fds_init(CP_FDS *fds, int maxevents, int timeout) |
| | | { |
| | | int rv = 0; |
| | | |
| | | if(NULL != fds) |
| | | { |
| | | memset(fds, 0, sizeof(*fds)); |
| | | fds->epfd = -1; |
| | | } |
| | | else |
| | | { |
| | | if( !(fds=(CP_FDS *)t_malloc(sizeof(*fds))) ) |
| | | { |
| | | log_err("fds context malloc failed: %s\n", strerror(errno)); |
| | | return NULL; |
| | | } |
| | | else |
| | | { |
| | | log_trace("malloc fds with address [%p]\n", fds); |
| | | memset(fds, 0, sizeof(*fds)); |
| | | fds->epfd = -1; |
| | | fds->flag |= FLAG_FDS_MALLOC; |
| | | } |
| | | } |
| | | |
| | | /* set maximum file descriptor number that can be opened in this process */ |
| | | maxevents = maxevents<CP_DEF_MAX_EVENTS ? maxevents : CP_DEF_MAX_EVENTS; |
| | | if( cp_fds_setrlimit(maxevents) ) |
| | | { |
| | | rv = -2; |
| | | goto cleanup; |
| | | } |
| | | |
| | | /* Create epoll file description */ |
| | | fds->epfd = epoll_create(maxevents); |
| | | if(fds->epfd < 0) |
| | | { |
| | | rv = -3; |
| | | log_fatal("epoll_create failed: %s\n", strerror(errno)); |
| | | goto cleanup; |
| | | } |
| | | log_trace("Open epoll file description [%d]\n", fds->epfd); |
| | | |
| | | /* Initialise the server/client/task list */ |
| | | INIT_LIST_HEAD(&fds->server_list); |
| | | INIT_LIST_HEAD(&fds->client_list); |
| | | fds->task_array = cp_array_init(NULL, maxevents); |
| | | fds->event_queue = cp_queue_init(NULL, maxevents); |
| | | |
| | | fds->timeout = timeout<0 ? -1 : timeout; |
| | | fds->max_event = maxevents; |
| | | fds->flag |= FLAG_FDS_INIT; |
| | | |
| | | cleanup: |
| | | if(rv) |
| | | { |
| | | log_err("Initialise fds contex failed\n"); |
| | | cp_fds_term(fds); |
| | | return NULL; |
| | | } |
| | | |
| | | log_nrml("Initialise fds contex [%p] ok\n", fds); |
| | | return fds; |
| | | } |
| | | |
| | | /* Terminate $fds context, if $fds malloced, then free it */ |
| | | void cp_fds_term(CP_FDS *fds) |
| | | { |
| | | log_dbg("terminate epoll fds contex now\n"); |
| | | |
| | | if(!fds) |
| | | { |
| | | log_err("Invalude input arguments\n"); |
| | | return; |
| | | } |
| | | |
| | | if(fds->epfd >= 0) |
| | | { |
| | | log_dbg("Close epoll file description [%d]\n", fds->epfd); |
| | | close(fds->epfd); |
| | | } |
| | | |
| | | if(fds->task_array) |
| | | { |
| | | cp_array_term(fds->task_array); |
| | | } |
| | | |
| | | if(fds->event_queue) |
| | | { |
| | | cp_queue_destroy(fds->event_queue); |
| | | } |
| | | |
| | | if(fds->flag& FLAG_FDS_MALLOC) |
| | | { |
| | | t_free(fds); |
| | | } |
| | | |
| | | log_nrml("Terminate epoll fds contex ok.\n"); |
| | | |
| | | return ; |
| | | } |
| | | |
| | | /* epoll_ctl() to add this socket to epoll */ |
| | | int cp_add_epoll_event(CP_SOCK *sock) |
| | | { |
| | | int rv = 0; |
| | | CP_FDS *fds; |
| | | |
| | | if( !sock || !(fds=sock->fds) ) |
| | | { |
| | | log_err("Invalude input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | if( sock->flag&FLAG_SOCK_EPOLLED ) |
| | | return 0; /* already put in epoll */ |
| | | |
| | | if(fds->event_cnt > fds->max_event) |
| | | { |
| | | log_fatal("No more epoll event space [%d/%d] for socket[%d]\n", |
| | | fds->event_cnt, fds->max_event, sock->fd); |
| | | return -2; |
| | | } |
| | | |
| | | memset(&sock->event, 0, sizeof(sock->event)); |
| | | sock->event.events = EPOLLIN; |
| | | sock->event.data.ptr = sock; |
| | | |
| | | if ( epoll_ctl (fds->epfd, EPOLL_CTL_ADD, sock->fd, &sock->event) < 0) |
| | | { |
| | | if(EEXIST == errno) |
| | | { |
| | | log_warn("socket[%d] already registe in epoll\n", sock->fd); |
| | | goto cleanup; |
| | | } |
| | | else |
| | | { |
| | | log_err("socket[%d] registe in epoll failed: %s\n", sock->fd, strerror(errno)); |
| | | rv = -3; |
| | | goto cleanup; |
| | | } |
| | | } |
| | | |
| | | fds->event_cnt++; |
| | | sock->flag |= FLAG_SOCK_EPOLLED; |
| | | |
| | | cleanup: |
| | | if(rv) |
| | | log_err("add socket [%d] to epoll event failed\n", sock->fd); |
| | | else |
| | | log_dbg("add socket [%d] to epoll event ok\n", sock->fd); |
| | | |
| | | return rv; |
| | | } |
| | | |
| | | |
| | | /* epoll_ctl() to mod this socket in epoll */ |
| | | int cp_mod_epoll_event(CP_SOCK *sock, int event) |
| | | { |
| | | CP_FDS *fds; |
| | | |
| | | if( !sock || !(fds=sock->fds) ) |
| | | { |
| | | log_err("Invalude input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | if( !(sock->flag&FLAG_SOCK_EPOLLED) ) |
| | | { |
| | | return -2; /* not in epoll */ |
| | | } |
| | | |
| | | sock->event.events = event; |
| | | if ( epoll_ctl (fds->epfd, EPOLL_CTL_MOD, sock->fd, &sock->event) < 0) |
| | | { |
| | | log_err("modidfy socket [%d] epoll event failed: %s\n", sock->fd, strerror(errno)); |
| | | return -3; |
| | | } |
| | | |
| | | log_dbg("modidfy socket [%d] epoll event ok\n", sock->fd); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | void cp_del_epoll_event(CP_SOCK *sock) |
| | | { |
| | | CP_FDS *fds; |
| | | |
| | | if( !sock || !(fds=sock->fds) ) |
| | | { |
| | | log_err("Invalude input arguments\n"); |
| | | return; |
| | | } |
| | | |
| | | if( !(sock->flag&FLAG_SOCK_EPOLLED) ) |
| | | return; /* not in epoll */ |
| | | |
| | | sock->flag &= ~FLAG_SOCK_EPOLLED; |
| | | epoll_ctl(fds->epfd, EPOLL_CTL_DEL, sock->fd, NULL); |
| | | fds->event_cnt--; |
| | | |
| | | log_dbg("remove socket [%d] from epoll event ok\n", sock->fd); |
| | | return ; |
| | | } |
| | | |
| | | /* add the listen/connect socket into server_list/client_list */ |
| | | int cp_fds_add_sock_registry(CP_SOCK *sock) |
| | | { |
| | | CP_FDS *fds; |
| | | |
| | | if( !sock || !(fds=sock->fds) ) |
| | | { |
| | | log_err("Invalude input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | if( sock->flag&FLAG_SOCK_REGISTRY ) |
| | | return 0; /* already in registry list */ |
| | | |
| | | if(CP_SOCK_MODE_CONNECT == sock->mode) |
| | | { |
| | | log_dbg("regist socket [%p] on CONNECT mode into client list ok\n", sock); |
| | | list_add_tail(&sock->rlist, &fds->client_list); |
| | | } |
| | | else if(CP_SOCK_MODE_LISTEN == sock->mode) |
| | | { |
| | | log_dbg("regist socket [%p] on LISTEN mode into server list ok\n", sock); |
| | | list_add_tail(&sock->rlist, &fds->server_list); |
| | | } |
| | | else if(CP_SOCK_MODE_ACCEPT==sock->mode && sock->serv_sock) |
| | | { |
| | | log_dbg("regist socket [%p] on ACCEPT mode into server list ok\n", sock); |
| | | list_add_tail(&sock->rlist, &sock->serv_sock->accept_list); |
| | | sock->serv_sock->accept_cnt++; |
| | | } |
| | | else |
| | | { |
| | | log_err("regist socket [%p] on mode %d into client/server list failed: Unsupport mode.\n", sock, sock->mode); |
| | | return -2; |
| | | } |
| | | |
| | | sock->flag |= FLAG_SOCK_REGISTRY; |
| | | return 0; |
| | | } |
| | | |
| | | /* remove the listen/connect socket from server_list/client_list */ |
| | | void cp_fds_del_sock_registry(CP_SOCK *sock) |
| | | { |
| | | if(!sock || !(sock->flag&FLAG_SOCK_REGISTRY) ) |
| | | return; /* not in registry list */ |
| | | |
| | | if(CP_SOCK_MODE_ACCEPT==sock->mode && sock->serv_sock) |
| | | sock->serv_sock->accept_cnt--; |
| | | |
| | | log_dbg("remove socket [%d] from socket registry list ok\n", sock->fd); |
| | | list_del(&sock->rlist); |
| | | sock->flag &= ~FLAG_SOCK_REGISTRY; |
| | | |
| | | return ; |
| | | } |
| | | |
| | | |
| | | /* Add a socket in task list */ |
| | | int cp_fds_add_sock_task(CP_SOCK *sock) |
| | | { |
| | | CP_FDS *fds; |
| | | int rv; |
| | | |
| | | if( !sock || !(fds=sock->fds) ) |
| | | { |
| | | log_err("Invalude input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | if( sock->flag&FLAG_SOCK_TASKED ) |
| | | return 0; /* already in a list */ |
| | | |
| | | log_info("add socket [%d] into task list\n", sock->fd); |
| | | if( (rv=cp_array_add(fds->task_array, sock)) >=0 ) |
| | | { |
| | | sock->index = rv; |
| | | sock->flag |= FLAG_SOCK_TASKED; |
| | | return 0; |
| | | } |
| | | |
| | | return -2; |
| | | } |
| | | |
| | | void cp_fds_del_sock_task(CP_SOCK *sock) |
| | | { |
| | | if(!sock || !(sock->flag&FLAG_SOCK_TASKED)) |
| | | return ; |
| | | |
| | | log_info("remove socket [%d:%p] from task list[%p] by index [%d]\n", sock->fd, sock, sock->fds->task_array, sock->index); |
| | | |
| | | if(sock->index >= 0) |
| | | cp_array_rm_byindex(sock->fds->task_array, sock->index); |
| | | else |
| | | cp_array_rm_bydata(sock->fds->task_array, sock); |
| | | |
| | | sock->flag &= ~FLAG_SOCK_TASKED; |
| | | sock->index = -1; |
| | | memset(&sock->event, 0, sizeof(struct epoll_event)); |
| | | |
| | | return ; |
| | | } |
| | | |
| | | void *cp_fds_sock_enqueue(CP_SOCK *sock) |
| | | { |
| | | if(!sock || sock->flag&FLAG_SOCK_INQUEUE || sock->flag&FLAG_SOCK_TASKED || !sock->fds) |
| | | return NULL; |
| | | |
| | | sock->flag |= FLAG_SOCK_INQUEUE; |
| | | return cp_enqueue(sock->fds->event_queue, sock); |
| | | } |
| | | |
| | | void *cp_fds_sock_dequeue(CP_FDS *fds) |
| | | { |
| | | CP_SOCK *sock = NULL; |
| | | |
| | | if( !fds ) |
| | | return NULL; |
| | | |
| | | sock = cp_dequeue(fds->event_queue); |
| | | sock->flag &= ~FLAG_SOCK_INQUEUE; |
| | | |
| | | return sock; |
| | | } |
| | | |
| | | void *cp_fds_sock_rmqueue(CP_SOCK *sock) |
| | | { |
| | | if(!sock || !(sock->flag&FLAG_SOCK_INQUEUE) || !sock->fds) |
| | | return NULL; |
| | | |
| | | sock->flag &= ~FLAG_SOCK_INQUEUE; |
| | | return cp_rmqueue(sock->fds->event_queue, sock); |
| | | } |
| | | |
| | | void cp_fds_list_sock_task(CP_FDS *fds) |
| | | { |
| | | int i; |
| | | CP_SOCK *sock; |
| | | |
| | | if(!fds) |
| | | return ; |
| | | |
| | | log_dbg("list all the socket in task list:\n"); |
| | | |
| | | /* list all the socket from task list */ |
| | | cp_list_array_for_each(fds->task_array, i, sock) |
| | | { |
| | | if(sock) |
| | | log_dbg("socket[%d:%p] in task list\n", sock->fd, sock); |
| | | } |
| | | |
| | | return ; |
| | | } |
| | | |
| | | |
| | | void cp_fds_destroy_sock(CP_SOCK *sock) |
| | | { |
| | | cp_fds_del_sock_task(sock); |
| | | cp_fds_sock_rmqueue(sock); |
| | | cp_del_epoll_event(sock); |
| | | cp_fds_del_sock_registry(sock); |
| | | cp_sock_term(sock); |
| | | |
| | | return ; |
| | | } |
| | | |
| | | |
| | | int cp_fds_detect_event(CP_FDS *fds) |
| | | { |
| | | int i=0, nfds=0; |
| | | CP_SOCK *sock; |
| | | struct epoll_event evts[CP_MAX_EVENT_ONCE]; |
| | | |
| | | if( !fds ) |
| | | return -1; |
| | | |
| | | nfds = epoll_wait(fds->epfd, evts, CP_MAX_EVENT_ONCE, fds->timeout); |
| | | ///if(nfds<0 && errno!=EINTR) |
| | | if(nfds<0) |
| | | { |
| | | log_fatal("epoll_wait failure: %s\n", strerror(errno)); |
| | | return -2; |
| | | } |
| | | |
| | | if(nfds == 0) |
| | | return 0; |
| | | |
| | | log_dbg("epoll_wait get [%d] events\n", nfds); |
| | | |
| | | for (i=0; i<nfds; i++) |
| | | { |
| | | sock=(CP_SOCK *)evts[i].data.ptr; |
| | | sock->event = evts[i]; |
| | | sock->actv_time = time_now(); |
| | | |
| | | log_dbg("socket [%d] get event [0x%0x] and added to event queue ok\n", sock->fd, sock->event.events); |
| | | if( SOCK_STAT_ALREADY==sock->status ) |
| | | cp_fds_sock_enqueue(sock); |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | void cp_fds_proc_event(CP_FDS *fds) |
| | | { |
| | | int i; |
| | | CP_SOCK *sock; |
| | | int rv; |
| | | |
| | | if( !fds ) |
| | | return; |
| | | |
| | | //cp_fds_list_sock_task(fds); |
| | | |
| | | //log_trace("Start process the events....\n"); |
| | | |
| | | /* Process all the socket in task list first, its urgent */ |
| | | cp_list_array_for_each(fds->task_array, i, sock) |
| | | { |
| | | if(sock) |
| | | { |
| | | if(sock->cbfunc) |
| | | { |
| | | log_dbg("Process socket [%d] in task list on event [%d]\n", sock->fd, sock->event.events); |
| | | rv = sock->cbfunc(sock); |
| | | } |
| | | else |
| | | { |
| | | log_err("Process Socket [%d:%p] not implement event callback and remove it\n", sock->fd, sock); |
| | | cp_fds_del_sock_task(sock); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* Process all the socket in event queue now */ |
| | | while(!cp_queue_is_empty(fds->event_queue)) |
| | | { |
| | | if( NULL!= (sock=cp_fds_sock_dequeue(fds)) ) |
| | | { |
| | | //log_dbg("after handle one socket count: %d\n", cp_queue_count(fds->event_queue)); |
| | | if(sock->cbfunc) |
| | | { |
| | | log_dbg("Process socket [%d %p] in event queue on event [%d]\n", sock->fd, sock, sock->event.events); |
| | | rv = sock->cbfunc(sock); |
| | | } |
| | | else |
| | | { |
| | | log_err("Process Socket [%d:%p] not implement event callback and remove it\n", sock->fd, sock); |
| | | } |
| | | } |
| | | } |
| | | |
| | | //log_trace("End process the events....\n"); |
| | | return; |
| | | } |
| | | |
| | | |
| | | void cp_sock_term_server(CP_SOCK *serv_sock) |
| | | { |
| | | CP_SOCK *sock, *tsock; |
| | | |
| | | log_warn("terminate server socket [%d] and [%d] accept client now\n", serv_sock->fd, serv_sock->accept_cnt); |
| | | list_for_each_entry_safe(sock, tsock, &serv_sock->accept_list, rlist) |
| | | { |
| | | /*remove all the accept socket from task and registry list, then destroy it*/ |
| | | //log_warn("destroy accept socket [%d:%p]\n", sock->fd, sock); |
| | | cp_fds_destroy_sock(sock); |
| | | } |
| | | |
| | | /*remove this server socket from task and registry list, then destroy it*/ |
| | | log_warn("terminate server socket [%d] and its accept client ok\n", serv_sock->fd); |
| | | cp_fds_destroy_sock(serv_sock); |
| | | |
| | | return ; |
| | | } |
| | | |
| | | |
| | | void cp_sock_term_all_server(CP_FDS *fds) |
| | | { |
| | | CP_SOCK *sock, *tsock; |
| | | |
| | | log_dbg("destroy all the listen socket now\n"); |
| | | |
| | | /* Terminate all the listen socket */ |
| | | list_for_each_entry_safe(sock, tsock, &fds->server_list, rlist) |
| | | { |
| | | cp_sock_term_server(sock); |
| | | } |
| | | |
| | | log_warn("destroy all the listen socket ok\n"); |
| | | |
| | | return ; |
| | | } |
| | | |
| | | |
| | | void cp_sock_term_all_client(CP_FDS *fds) |
| | | { |
| | | CP_SOCK *sock = NULL, *tsock; |
| | | |
| | | log_dbg("destroy all the connect socket now\n"); |
| | | /* Terminate all the listen socket */ |
| | | list_for_each_entry_safe(sock, tsock, &fds->client_list, rlist) |
| | | { |
| | | /*remove all the connect socket from task and registry list, then destroy it*/ |
| | | cp_fds_destroy_sock(sock); |
| | | } |
| | | log_warn("destroy all the connect socket ok\n"); |
| | | } |
| | | |
| | | /* Checkout the socket timeout happened or not, if happened then put it in task list */ |
| | | void cp_sock_detect_timeout(CP_FDS *fds) |
| | | { |
| | | CP_SOCK *sock, *tsock, *serv_sock; |
| | | |
| | | /* check all the connect socket timeout */ |
| | | list_for_each_entry_safe(sock, tsock, &fds->client_list, rlist) |
| | | { |
| | | /*If the socket timeout value and timeout, then disconnect it */ |
| | | if( sock->idle_timeout>0 && time_elapsed(sock->actv_time)>sock->idle_timeout ) |
| | | { |
| | | log_warn("socket[%d] idle timeout happened and add to task list\n", sock->fd); |
| | | log_dbg("last: %lu elapsed time: %lu idel timeout: %lu\n", sock->actv_time, time_elapsed(sock->actv_time), sock->idle_timeout); |
| | | sock->event.events = CP_SOCK_EVENT_IDLE_TIMEOUT; |
| | | cp_fds_add_sock_task(sock); |
| | | } |
| | | else if( sock->msg_timeout>0 && sock->msg_time>0 && time_elapsed(sock->msg_time)>sock->msg_timeout ) |
| | | { |
| | | log_warn("socket[%d] message timeout happened and add to task list\n", sock->fd); |
| | | sock->event.events = CP_SOCK_EVENT_MSG_TIMEOUT; |
| | | cp_fds_add_sock_task(sock); |
| | | } |
| | | } |
| | | |
| | | /* check all the accept socket timeout */ |
| | | list_for_each_entry(serv_sock, &fds->server_list, rlist) |
| | | { |
| | | list_for_each_entry_safe(sock, tsock, &serv_sock->accept_list, rlist) |
| | | { |
| | | /*If the socket timeout value and timeout, then disconnect it */ |
| | | if( sock->idle_timeout>0 && time_elapsed(sock->actv_time)>sock->idle_timeout ) |
| | | { |
| | | sock->event.events = CP_SOCK_EVENT_IDLE_TIMEOUT; |
| | | log_warn("socket[%d] idle timeout happened and add to task list\n", sock->fd); |
| | | log_dbg("last: %lu elapsed time: %lu idel timeout: %lu\n", sock->actv_time, time_elapsed(sock->actv_time), sock->idle_timeout); |
| | | cp_fds_add_sock_task(sock); |
| | | } |
| | | else if( sock->msg_timeout>0 && sock->msg_time>0 && time_elapsed(sock->msg_time)>sock->msg_timeout ) |
| | | { |
| | | sock->event.events = CP_SOCK_EVENT_MSG_TIMEOUT; |
| | | log_warn("socket[%d] message timeout happened and add to task list\n", sock->fd); |
| | | cp_fds_add_sock_task(sock); |
| | | } |
| | | } /* list_for_each_entry_safe server accept socket list */ |
| | | } /* list_for_each_entry all the server socket list */ |
| | | } |
| | | |
| | | |
| | | void cp_sock_term_all_task(CP_FDS *fds) |
| | | { |
| | | int i; |
| | | CP_SOCK *sock; |
| | | |
| | | log_dbg("remove all the socket in task list now\n"); |
| | | |
| | | /* remove all the socket from task array */ |
| | | cp_list_array_for_each(fds->task_array, i, sock) |
| | | { |
| | | //log_warn("remove socket[%d] in task list ok\n", sock->fd); |
| | | if(sock) |
| | | cp_fds_del_sock_task(sock); |
| | | } |
| | | |
| | | while( !cp_queue_is_empty(fds->event_queue) ) |
| | | { |
| | | cp_dequeue(fds->event_queue); |
| | | } |
| | | |
| | | log_warn("remove all the socket in task list ok\n"); |
| | | |
| | | return ; |
| | | } |
| | | |
| | | |
| | | |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_fds.h |
| | | * Description: This head file |
| | | * |
| | | * Version: 1.0.0(10/25/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "10/25/2012 04:55:37 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #ifndef __CP_FDS_H |
| | | #define __CP_FDS_H |
| | | |
| | | #include <stdio.h> |
| | | #include <unistd.h> |
| | | #include <stdlib.h> |
| | | #include <errno.h> |
| | | #include <string.h> |
| | | |
| | | #include <sys/epoll.h> |
| | | |
| | | #include "cp_klist.h" |
| | | #include "cp_logger.h" |
| | | #include "cp_sock.h" |
| | | #include "cp_queue.h" |
| | | #include "cp_array.h" |
| | | |
| | | #define CP_MAX_EVENT_ONCE 128 |
| | | #define CP_DEF_MAX_EVENTS 1024 |
| | | #define CP_DEF_FDS_TIMEOUT 10 |
| | | |
| | | #define IN_EVENT_LIST 0 |
| | | #define IN_TASK_LIST 1 |
| | | |
| | | #define FLAG_FDS_INIT (1<<0) |
| | | #define FLAG_FDS_MALLOC (1<<1) |
| | | |
| | | struct _CP_SOCK; |
| | | struct _CP_FDS; |
| | | |
| | | typedef struct _CP_FDS |
| | | { |
| | | unsigned char flag; /* Refer to follow definition */ |
| | | int epfd; /* the epoll_create() returns file description */ |
| | | int timeout; /* epoll_wait timeout value */ |
| | | int max_event; /* Maximum monitor FD number */ |
| | | int event_cnt; /* current socket regist in epoll */ |
| | | |
| | | struct list_head server_list; /* a list keep all the listen sockets */ |
| | | struct list_head client_list; /* a list keep all the connect sockets */ |
| | | CP_QUEUE *event_queue; /* a queue keep all these sockets get event happened */ |
| | | CP_ARRAY *task_array; /* an array keep all these pending/or other special task socket */ |
| | | |
| | | /* flag definitions |
| | | * 0 0 0 0 0 1 1 1 |
| | | * | | | | |______ Initial or not - 0: No 1: Yes |
| | | * | | | |________ Malloc or not - 0: Variable, 1: Malloc |
| | | * | | |__________ Stop or not - 0: Not stop 1: Stop |
| | | * | |____________ Reserved |
| | | * |____________________ Reserved |
| | | */ |
| | | } CP_FDS; |
| | | |
| | | /* Initialze $fds context, if $fds is NULL, then malloc it */ |
| | | extern CP_FDS *cp_fds_init(CP_FDS *fds, int maxevents, int timeout); |
| | | /* Terminate $fds context, if $fds malloced, then free it */ |
| | | extern void cp_fds_term(CP_FDS *fds); |
| | | #define cp_fds_term_clear(fds) {cp_fds_term(fds); fds=NULL;} |
| | | |
| | | /* epoll_ctl() to add this socket to epoll */ |
| | | int cp_add_epoll_event(struct _CP_SOCK *sock); |
| | | /* epoll_ctl() to mod this socket in epoll */ |
| | | int cp_mod_epoll_event(struct _CP_SOCK *sock, int event); |
| | | /* epoll_ctl() to del this socket from epoll */ |
| | | void cp_del_epoll_event(struct _CP_SOCK *sock); |
| | | |
| | | |
| | | /* add the socket into the socket registry list */ |
| | | int cp_fds_add_sock_registry(struct _CP_SOCK *sock); |
| | | /* remove the socket from the socket registry list */ |
| | | void cp_fds_del_sock_registry(struct _CP_SOCK *sock); |
| | | |
| | | /* add the socket into task list */ |
| | | int cp_fds_add_sock_task(struct _CP_SOCK *sock); |
| | | /* remove the socket from event or task list */ |
| | | void cp_fds_del_sock_task(struct _CP_SOCK *sock); |
| | | /* list all the socket from task list */ |
| | | void cp_fds_list_sock_task(CP_FDS *fds); |
| | | |
| | | void *cp_fds_sock_enqueue(struct _CP_SOCK *sock); |
| | | void *cp_fds_sock_rmqueue(struct _CP_SOCK *sock); |
| | | void *cp_fds_sock_dequeue(CP_FDS *fds); |
| | | |
| | | /* remove the socket from task and registry list and destroy it */ |
| | | void cp_fds_destroy_sock(struct _CP_SOCK *sock); |
| | | #define cp_fds_destroy_sock_clear(sock) {cp_fds_destroy_sock(sock); sock=NULL;} |
| | | |
| | | /* epoll_wait detect all these socket get event and add it to task list */ |
| | | extern int cp_fds_detect_event(CP_FDS *fds); |
| | | /* process all these socket get event and add it to task list */ |
| | | extern void cp_fds_proc_event(CP_FDS *fds); |
| | | /* Detect all these socket get timeout and add it to task list */ |
| | | extern void cp_sock_detect_timeout(CP_FDS *fds); |
| | | |
| | | |
| | | extern void cp_sock_term_server(struct _CP_SOCK *serv_sock); |
| | | extern void cp_sock_term_all_server(CP_FDS *fds); |
| | | extern void cp_sock_term_all_client(CP_FDS *fds); |
| | | extern void cp_sock_term_all_task(CP_FDS *fds); |
| | | |
| | | #endif /* __CP_FDS_H */ |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) guowenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: module.c |
| | | * Description: This is the GPRS Power/SIM card control source code |
| | | * |
| | | * Version: 1.0.0(02/07/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "02/07/2012 03:08:25 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include "cp_gprs.h" |
| | | #include "cp_hal.h" |
| | | #include "cp_proc.h" |
| | | #include "cp_gsmmux.h" |
| | | #include "at91_ioctl.h" |
| | | |
| | | int init_gsm_module(MODULE_INFO *module) |
| | | { |
| | | int i=0; |
| | | char devname[DEVNAME_LEN]; |
| | | |
| | | log_info("Initialize GSM module context\n"); |
| | | |
| | | memset(module, 0, sizeof(*module)); |
| | | |
| | | module->event = REQ_POWER_RESET; /* Request to power on GPRS */ |
| | | |
| | | pthread_mutex_init(&module->lock, NULL); |
| | | |
| | | if( !(module->gsmport=comport_init(GSM_DATAPORT, 115200, "8N1N")) ) |
| | | { |
| | | return -1; |
| | | } |
| | | |
| | | /* Initialize the GPRS dataport pointer */ |
| | | module->comport_cnt = MAX_DATAPORT; |
| | | for(i=0; i<module->comport_cnt; i++) |
| | | { |
| | | snprintf(devname, DEVNAME_LEN, "%s%d", CMUX_DATAPORT, i+CMUX_PORT_START_INDEX); |
| | | module->comport[i] = comport_init(devname, 115200, "8N1N"); |
| | | if(NULL == module->comport[i]) |
| | | goto ERROR; |
| | | |
| | | //log_dbg("Initialise comport [%p] on %s on baudrate 115200 with 8N1N\n", module->comport[i], devname); |
| | | } |
| | | |
| | | return 0; |
| | | |
| | | ERROR: |
| | | while(i-- >= 0) |
| | | { |
| | | comport_term(module->comport[i]); |
| | | } |
| | | return -2; |
| | | } |
| | | |
| | | |
| | | /* |
| | | * Description: close all the GPRS control port device. |
| | | * |
| | | * Return Value: NONE |
| | | */ |
| | | void close_gsm_dataport(MODULE_INFO *module) |
| | | { |
| | | int i; |
| | | |
| | | for(i=0; i<module->comport_cnt; i++) |
| | | { |
| | | log_nrml("Close GPRS dataport %s=>[fd:%d]\n", module->comport[i]->dev_name, module->comport[i]->fd); |
| | | comport_close(module->comport[i]); |
| | | } |
| | | |
| | | return ; |
| | | } |
| | | |
| | | /* |
| | | * Description: open all the GPRS data port device. |
| | | * |
| | | * Return Value: 0: Open successfully !0: Open failure |
| | | */ |
| | | int open_gsm_dataport(MODULE_INFO *module) |
| | | { |
| | | int i, retval = -1; |
| | | |
| | | for(i=0; i<module->comport_cnt; i++) |
| | | { |
| | | if( (retval=comport_open(module->comport[i])) < 0) |
| | | { |
| | | log_err("Open GPRS dataport %s failure: %d\n", module->comport[i]->dev_name, retval); |
| | | goto ERROR; |
| | | } |
| | | log_nrml("Open GPRS dataport[%p] %s=>[fd:%d]\n", module->comport, module->comport[i]->dev_name, module->comport[i]->fd); |
| | | } |
| | | |
| | | return 0; |
| | | |
| | | ERROR: |
| | | close_gsm_dataport(module); |
| | | return retval; |
| | | } |
| | | |
| | | |
| | | /* |
| | | * Description: Alloc a comport from the comport poor for used, for we must make sure |
| | | * PPP thread can grasp a comport to work, so we will always preserved |
| | | * first comport for PPP thread. |
| | | * |
| | | * Return Value: NULL: No comport left !NULL: The alloced comport pointer |
| | | */ |
| | | COM_PORT *alloc_gsm_dataport(char *who, MODULE_INFO *module) |
| | | { |
| | | static int lock = 0; |
| | | int i; |
| | | COM_PORT *comport = NULL; |
| | | |
| | | if(lock) |
| | | return NULL; |
| | | |
| | | lock = 1; |
| | | |
| | | /* Preserve first comport for PPP thread */ |
| | | for(i=0; i<module->comport_cnt; i++) |
| | | { |
| | | if(module->comport[i]->used != YES) |
| | | { |
| | | comport = module->comport[i]; |
| | | comport->used = YES; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | lock = 0; |
| | | |
| | | if(comport) |
| | | { |
| | | log_dbg("%s allocate GPRS dataport[%d] %s=>[fd:%d] ok\n", who, i, comport->dev_name, comport->fd); |
| | | module->users++; |
| | | } |
| | | else |
| | | { |
| | | log_dbg("%s allocate GPRS dataport failure\n", who); |
| | | } |
| | | |
| | | |
| | | return comport; |
| | | } |
| | | |
| | | /* |
| | | * Description: Free a comport to the comport poor when we no need it. |
| | | * |
| | | * Return Value: NONE |
| | | */ |
| | | void free_gsm_dataport(char *who, MODULE_INFO *module, COM_PORT **comport) |
| | | { |
| | | int i; |
| | | |
| | | /* Preserve first comport for PPP thread */ |
| | | for(i=0; i<module->comport_cnt; i++) |
| | | { |
| | | if(module->comport[i] == *comport) |
| | | { |
| | | log_dbg("%s free GPRS dataport %s=>[fd:%d]\n", who, (*comport)->dev_name, (*comport)->fd); |
| | | module->comport[i]->used = NO; |
| | | module->users--; |
| | | *comport = NULL; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | return ; |
| | | } |
| | | |
| | | |
| | | /* |
| | | * Description: Power on the GPRS module and open all the gprs data port. For when GPRS power off, |
| | | * the GPRS module USB convert serial comport device lost, so we must bind them together. |
| | | * Return Value: 0: Open successfully !0: Open failure |
| | | */ |
| | | int power_on_module(MODULE_INFO *module) |
| | | { |
| | | int rv = 0; |
| | | log_dbg("Turn on GPRS module now\n"); |
| | | |
| | | if( ON == (module->pwr_status=hal_get_gprs_power()) ) |
| | | { |
| | | rv = 0; |
| | | log_dbg("GPRS module already power on\n"); |
| | | goto cleanup; |
| | | } |
| | | |
| | | if( (rv=hal_turn_gprs_power(ON)) || ON!=hal_get_gprs_power()) |
| | | { |
| | | log_err("Turn on GPRS module failure: rv=%d power=%d\n", rv, hal_get_gprs_power()); |
| | | rv = -1; |
| | | goto cleanup; |
| | | } |
| | | |
| | | micro_second_sleep(500); |
| | | |
| | | if( comport_open(module->gsmport) < 0) |
| | | { |
| | | log_err("Open GSM serial port [%s] failure\n", module->gsmport->dev_name); |
| | | return -2; |
| | | } |
| | | |
| | | if( !atcmd_check_power_on(module->gsmport) ) |
| | | { |
| | | log_err("Send ATE0 check GPRS module AT command failure\n", module->gsmport->dev_name); |
| | | return -2; |
| | | } |
| | | |
| | | attach_gsm0710(module->gsmport); |
| | | |
| | | if( 0 != open_gsm_dataport(module) ) |
| | | { |
| | | rv = -3; |
| | | log_err("Open GPRS module comport failure\n"); |
| | | goto cleanup; |
| | | } |
| | | |
| | | cleanup: |
| | | |
| | | if(!rv) |
| | | { |
| | | module->ready = MODULE_READY; |
| | | log_nrml("Turn on GPRS module succesfully\n"); |
| | | } |
| | | else |
| | | { |
| | | module->ready = NOT_READY; |
| | | log_nrml("Turn on GPRS module failed, rv=%d\n", rv); |
| | | } |
| | | |
| | | module->ready = 0!=rv ? NOT_READY : MODULE_READY; |
| | | memset(&(module->reg), 0, sizeof(REGISTER_INFO)); |
| | | module->pwr_status = hal_get_gprs_power(); |
| | | |
| | | return rv; |
| | | } |
| | | |
| | | /* |
| | | * Description: Power off the GPRS module and close all the gprs data port. For when GPRS power off, |
| | | * the GPRS module USB convert serial comport device lost, so we must bind them together. |
| | | * Return Value: 0: Open successfully !0: Open failure |
| | | */ |
| | | int power_off_module(MODULE_INFO *module) |
| | | { |
| | | if( OFF == (module->pwr_status=hal_get_gprs_power()) ) |
| | | { |
| | | log_dbg("GPRS module already power off\n"); |
| | | return 0; |
| | | } |
| | | |
| | | while(module->users) |
| | | { |
| | | log_warn("%d application still use the GPRS module dataport, wait released...\n", module->users); |
| | | sleep(1); |
| | | } |
| | | |
| | | log_nrml("Turn off GPRS module now\n"); |
| | | close_gsm_dataport(module); |
| | | |
| | | comport_close(module->gsmport); |
| | | hal_turn_gprs_power(OFF); |
| | | |
| | | module->ready = NOT_READY; |
| | | memset(&(module->reg), 0, sizeof(REGISTER_INFO)); |
| | | module->pwr_status = hal_get_gprs_power(); |
| | | |
| | | micro_second_sleep(800); |
| | | return 0; |
| | | } |
| | | |
| | | void set_module_event(MODULE_INFO *module, int request) |
| | | { |
| | | log_dbg("Set the module event request[%d]\n", request); |
| | | pthread_mutex_lock(&module->lock); |
| | | module->event = request; |
| | | pthread_mutex_unlock(&module->lock); |
| | | } |
| | | |
| | | /* |
| | | * Description: Set the GPRS power status according to the module request event. |
| | | * the GPRS module USB convert serial comport device lost, so we must bind them together. |
| | | * Return Value: 0:Set GPRS power status successfully !0: Open failure |
| | | */ |
| | | int set_module_event_power(MODULE_INFO *module) |
| | | { |
| | | int rv = 0; |
| | | switch (module->event) |
| | | { |
| | | case REQ_POWER_ON: |
| | | rv = power_on_module(module); |
| | | break; |
| | | |
| | | case REQ_POWER_OFF: |
| | | rv = power_off_module(module); |
| | | break; |
| | | |
| | | case REQ_POWER_RESET: |
| | | rv = power_off_module(module); |
| | | rv = power_on_module(module); |
| | | break; |
| | | } |
| | | |
| | | if( rv ) |
| | | { |
| | | log_nrml("Response for the GPRS request event %d failure, rv=%d\n", module->event, rv); |
| | | return rv; |
| | | } |
| | | else |
| | | { |
| | | log_nrml("Response for the GPRS request event %d and clear this event ok\n", module->event); |
| | | set_module_event(module, REQ_EVENT_NONE); |
| | | return 0; |
| | | } |
| | | } |
| | | |
| | | |
| | | int atcmd_inspect_status(MODULE_INFO *module) |
| | | { |
| | | COM_PORT *comport; |
| | | REGISTER_INFO *reg = &(module->reg); /* SIM card Register information */ |
| | | char *who = "atcmd_inspect_status()"; |
| | | |
| | | static unsigned long start_time ; |
| | | |
| | | /* Every 10 seconds we will inspect it */ |
| | | if(start_time && time_elapsed(start_time) < 10000) |
| | | { |
| | | return 0; |
| | | } |
| | | |
| | | start_time= time_now(); |
| | | |
| | | comport = alloc_gsm_dataport(who, module); |
| | | if(NULL != comport) |
| | | { |
| | | log_dbg("Alloc dataport %s=>[fd:%d]\n", comport->dev_name, comport->fd); |
| | | } |
| | | else |
| | | return -1; |
| | | |
| | | reg->signal = atcmd_check_gprs_signal(comport); |
| | | |
| | | atcmd_check_gprs_location(comport, ®->loc); |
| | | |
| | | log_dbg("Free dataport %s=>[fd:%d]\n", comport->dev_name, comport->fd); |
| | | free_gsm_dataport(who, module, &comport); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | /* |
| | | * Description: Check the AT command and SIM card ready or not |
| | | * Input value: times: Max check times |
| | | *Return Value: 1: Already OK 0: Still on test -1: Failure |
| | | * |
| | | */ |
| | | int atcmd_check_module_ready(COM_PORT *comport, int times) |
| | | { |
| | | int rv; |
| | | static int fail_cnt = 0; |
| | | |
| | | /* Send ATE0 to check GPRS module AT ready or not */ |
| | | rv = atcmd_check_at_ready(comport); |
| | | if(rv) |
| | | goto cleanup; |
| | | |
| | | /* Send AT+CPIN? to check SIM card valid or not */ |
| | | rv = atcmd_check_sim_valid(comport); |
| | | |
| | | cleanup: |
| | | if(rv) |
| | | { |
| | | if(fail_cnt < times) |
| | | { |
| | | fail_cnt ++; |
| | | return 0; |
| | | } |
| | | else |
| | | { |
| | | fail_cnt = 0; |
| | | return -1; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | fail_cnt = 0; |
| | | return 1; |
| | | } |
| | | } |
| | | |
| | | int atcmd_check_power_on(COM_PORT *comport) |
| | | { |
| | | int i, rv = 0; |
| | | |
| | | for(i=0; i<10; i++) |
| | | { |
| | | if( !atcmd_check_at_ready(comport) ) |
| | | { |
| | | rv = 1; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | return rv; |
| | | } |
| | | |
| | | /* |
| | | * Some preset command here, such as set Module as 2G mode |
| | | */ |
| | | int atcmd_module_preset(COM_PORT *comport) |
| | | { |
| | | int retval = 0; |
| | | |
| | | /* Send AT+COPS=0 to set GPRS module auto select an operator */ |
| | | if(0 != (retval=send_atcmd_check_ok(comport, "AT+COPS=0\r", 3000)) ) |
| | | { |
| | | log_warn("AT+COPS=0 Set Auto Select Carrier: [FAILED]\n"); |
| | | return -2; |
| | | } |
| | | log_nrml("AT+COPS=0 Set Auto Select Carrier: [OK]\n"); |
| | | |
| | | return retval; |
| | | } |
| | | |
| | | |
| | | int atcmd_check_hwinfo(COM_PORT *comport, HW_INFO *hw, int times) |
| | | { |
| | | int rv; |
| | | static int fail_cnt = 0; |
| | | |
| | | /* Send AT+CGMM to check GPRS module hardware name and type */ |
| | | rv = atcmd_check_gprs_name(comport, hw->model); |
| | | if(rv) |
| | | goto cleanup; |
| | | |
| | | /* Send AT+CGMR to check GPRS module hardware version */ |
| | | rv = atcmd_check_gprs_version(comport, hw->mrev); |
| | | if(rv) |
| | | goto cleanup; |
| | | |
| | | /* Send AT+CGSN to check GPRS module hardware IEMI number*/ |
| | | rv = atcmd_check_gprs_iemi(comport, hw->iemi); |
| | | |
| | | cleanup: |
| | | if(rv) |
| | | { |
| | | if(fail_cnt < times) |
| | | { |
| | | fail_cnt ++; |
| | | return 0; |
| | | } |
| | | else |
| | | { |
| | | fail_cnt = 0; |
| | | return -1; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | fail_cnt = 0; |
| | | return 1; |
| | | } |
| | | } |
| | | |
| | | |
| | | int atcmd_check_regist(COM_PORT *comport, REGISTER_INFO *reg, int times) |
| | | { |
| | | int rv = 0; |
| | | static int fail_cnt = 0; |
| | | |
| | | /* Send AT+CSQ to check GPRS signal strength */ |
| | | reg->signal = atcmd_check_gprs_signal(comport); |
| | | if(reg->signal<2 && reg->signal>31) |
| | | { |
| | | rv = -1; |
| | | goto cleanup; |
| | | } |
| | | |
| | | /* Send AT+CREG? to check SIM card regist to network or not */ |
| | | reg->type = atcmd_check_gprs_register(comport); |
| | | |
| | | if(REG_HOMEWORK==reg->type || REG_ROAMING== reg->type) |
| | | { |
| | | /* SIM card register successfully */ |
| | | log_nrml("SIM card register successfully.\n"); |
| | | rv = 0; |
| | | } |
| | | else if(REG_DENIED==reg->type) |
| | | { |
| | | /* SIM card can not register, so request to switch SIM card */ |
| | | log_err("SIM card regist denied.\n"); |
| | | rv = -2; |
| | | goto cleanup; |
| | | } |
| | | else |
| | | { |
| | | log_err("SIM card regist failure.\n"); |
| | | rv = -3; |
| | | goto cleanup; |
| | | } |
| | | |
| | | rv = atcmd_check_gprs_carrier(comport, reg->carrier); |
| | | if(rv) |
| | | { |
| | | rv = -4; |
| | | log_err("Check SIM card acrrier failure.\n"); |
| | | goto cleanup; |
| | | } |
| | | |
| | | rv = atcmd_check_gprs_mcc_mnc(comport, reg->loc.mcc_mnc); |
| | | if(rv) |
| | | { |
| | | rv = -4; |
| | | log_err("Check SIM card register MCC-MNC failure\n"); |
| | | goto cleanup; |
| | | } |
| | | |
| | | |
| | | cleanup: |
| | | if(rv) |
| | | { |
| | | if(fail_cnt < times) |
| | | { |
| | | fail_cnt ++; |
| | | return 0; |
| | | } |
| | | else |
| | | { |
| | | fail_cnt = 0; |
| | | return -1; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | fail_cnt = 0; |
| | | return 1; |
| | | } |
| | | |
| | | } |
| | | |
| | | int atcmd_check_network_info(COM_PORT *comport, REGISTER_INFO *reg) |
| | | { |
| | | int retval = 0; |
| | | |
| | | /* Send AT+COPS to check SIM card registed network carrier */ |
| | | retval = atcmd_check_gprs_carrier(comport, reg->carrier); |
| | | if(retval) return -1; |
| | | |
| | | /* Send AT+QGSMLOC=1 to check GPRS module location */ |
| | | retval = atcmd_check_gprs_location(comport, &(reg->loc)); |
| | | if(retval) return -3; |
| | | |
| | | return retval; |
| | | } |
| | | |
| | | |
| | | int atcmd_check_ready(MODULE_INFO *module) |
| | | { |
| | | int rv; |
| | | COM_PORT *comport; |
| | | char *who = "atcmd_check_ready()"; |
| | | |
| | | log_nrml("AT command check GPRS registry status now\n"); |
| | | /* Alloc a comport to send AT command */ |
| | | comport = alloc_gsm_dataport(who, module); |
| | | if(NULL == comport) |
| | | { |
| | | log_warn("Alloc dataport for %s() failure.\n", __FUNCTION__); |
| | | return -1; |
| | | } |
| | | log_dbg("Alloc dataport %s=>[fd:%d]\n", comport->dev_name, comport->fd); |
| | | |
| | | switch(module->ready) |
| | | { |
| | | case MODULE_READY: |
| | | rv = atcmd_check_module_ready(comport, 10); |
| | | if(rv > 0) |
| | | { |
| | | log_nrml("GPRS AT command ready and SIM card valid successfully\n"); |
| | | module->ready++; /* Continue to check, not break */ |
| | | } |
| | | else if(rv == 0) |
| | | { |
| | | log_nrml("GPRS AT command ready and SIM card valid check continue...\n"); |
| | | } |
| | | else if(rv < 0) |
| | | { |
| | | log_nrml("GPRS AT command ready and SIM card valid check failed\n"); |
| | | set_module_event(module, REQ_POWER_RESET); |
| | | } |
| | | break; |
| | | |
| | | case CHECK_HWINFO: |
| | | rv = atcmd_check_hwinfo(comport, &(module->hw), 10); |
| | | if(rv > 0) |
| | | { |
| | | log_nrml("Check the GPRS Module hardware information successfully\n"); |
| | | module->ready++; /* Continue to check, not break */ |
| | | } |
| | | else if(rv == 0) |
| | | { |
| | | log_nrml("Check the GPRS Module hardware information continue...\n"); |
| | | } |
| | | else if(rv < 0) |
| | | { |
| | | log_nrml("Check the GPRS Module hardware information failed...\n"); |
| | | set_module_event(module, REQ_POWER_RESET); |
| | | } |
| | | break; |
| | | |
| | | case CHECK_REGISTRY: |
| | | rv = atcmd_check_regist(comport, &(module->reg), 10); |
| | | if(rv > 0) |
| | | { |
| | | log_nrml("Check the SIM card registry successfully\n"); |
| | | module->ready++; /* Continue to check, not break */ |
| | | } |
| | | else if(rv == 0) |
| | | { |
| | | log_nrml("Check the SIM card registry continue...\n"); |
| | | } |
| | | else if(rv < 0) |
| | | { |
| | | log_nrml("Check the SIM card registry failed\n"); |
| | | set_module_event(module, REQ_POWER_RESET); |
| | | } |
| | | break; |
| | | } |
| | | |
| | | free_gsm_dataport(who, module, &comport); |
| | | return rv; |
| | | } |
| | | |
| | | |
| | | /* |
| | | * Description: Terminate the control thread work context |
| | | * Return Value: NONE |
| | | */ |
| | | void ctrl_thread_term(void *thread_arg) |
| | | { |
| | | int i=0; |
| | | MODULE_INFO *module = (MODULE_INFO *)thread_arg; |
| | | |
| | | log_nrml("start terminate GPRS main(control) thread\n"); |
| | | |
| | | power_off_module(module); |
| | | |
| | | for(i=0; i<module->comport_cnt; i++) |
| | | { |
| | | comport_term(module->comport[i]); |
| | | } |
| | | } |
| | | |
| | | |
| | | /* Description: Continue the main thread as the control thread, which used to control/inspect the GPRS |
| | | * module power status. If it exit, then whole program exit.So when it exit, we must |
| | | * make sure all other threads exit. |
| | | * |
| | | *Return Value: NONE |
| | | */ |
| | | void ctrl_thread_start(void *thread_arg) |
| | | { |
| | | MODULE_INFO *module = (MODULE_INFO *)thread_arg; |
| | | |
| | | log_nrml("GPRS power control thread start running\n"); |
| | | |
| | | while( !g_cp_signal.stop ) |
| | | { |
| | | /* If someone request to change the power status, then set the power*/ |
| | | if(module->event) |
| | | { |
| | | set_module_event_power(module); |
| | | } |
| | | |
| | | if(ALL_READY == module->ready) |
| | | { |
| | | /* If GPRS already registed then we just need to inspect the GPRS |
| | | * module status, such as signal, location */ |
| | | atcmd_inspect_status(module); |
| | | } |
| | | else |
| | | { |
| | | /* If GPRS module just already power on, then we use AT command to |
| | | * check the SIM card can work or not now. */ |
| | | if( ON == module->pwr_status ) |
| | | { |
| | | atcmd_check_ready(module); |
| | | } |
| | | } |
| | | |
| | | sleep(1); |
| | | } |
| | | |
| | | /* thread exit */ |
| | | ctrl_thread_term(thread_arg); |
| | | |
| | | return ; |
| | | } |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) guowenxue <guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: module.h |
| | | * Description: This is the GPRS module head file |
| | | * |
| | | * Version: 1.0.0(02/02/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "02/02/2012 11:33:33 AM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #ifndef __CP_GPRS_H |
| | | #define __CP_GPRS_H |
| | | |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <unistd.h> |
| | | #include <pthread.h> |
| | | |
| | | #include "cp_common.h" |
| | | #include "cp_logger.h" |
| | | #include "cp_comport.h" |
| | | #include "cp_atcmd.h" |
| | | #include "cp_time.h" |
| | | #include "cp_hal.h" |
| | | |
| | | #define YES 1 |
| | | #define NO 0 |
| | | |
| | | #define GSM_CTRLPORT "/dev/gprs" |
| | | #define GSM_DATAPORT "/dev/ttyS2" |
| | | |
| | | #define MAX_DATAPORT 4 /* CMUX driver will generate 4 TTY port */ |
| | | #define CMUX_PORT_START_INDEX 1 |
| | | #define CMUX_DATAPORT "/dev/gsmtty" |
| | | |
| | | /*GPRS module power status control request event*/ |
| | | enum |
| | | { |
| | | REQ_EVENT_NONE = 0, |
| | | REQ_POWER_OFF, |
| | | REQ_POWER_ON, |
| | | REQ_POWER_RESET, |
| | | }; |
| | | |
| | | /* GPRS Module Ready status */ |
| | | enum |
| | | { |
| | | NOT_READY, |
| | | MODULE_READY, /* GPRS AT command active and SIM card valid */ |
| | | CHECK_HWINFO, /* Get GPRS hardware Information */ |
| | | CHECK_REGISTRY, /* Check GPRS register network information */ |
| | | ALL_READY, |
| | | }; |
| | | |
| | | /* AT+CREG? command show SIM card register status */ |
| | | enum |
| | | { |
| | | REG_UNREGIST = 0, /* not registered, ME is not currently searching a new operator to register to */ |
| | | REG_HOMEWORK, /* registered, home network */ |
| | | REG_SEARCHING, /* not registered, but ME is currently searching a new operator to register to */ |
| | | REG_DENIED, /* registration denied */ |
| | | REG_UNKNOW, /* unknow */ |
| | | REG_ROAMING, /* registered, roaming */ |
| | | }; |
| | | |
| | | /* AT+CNMP=? command to set GPRS module work on which mode */ |
| | | #define MODE_AUTO 2 /* Automatic */ |
| | | #define MODE_GSM 13 /* GSM Only */ |
| | | #define MODE_WCDMA 14 /* WCDMA Only */ |
| | | |
| | | /* AT+CNSMOD? command show network system mode */ |
| | | enum |
| | | { |
| | | NS_NONE = 0, /* No service */ |
| | | NS_GSM, /* GSM */ |
| | | NS_GPRS, /* GPRS */ |
| | | NS_EGPRS, /* EGPRS(EDGE) */ |
| | | NS_WCDMA, /* WCDMA */ |
| | | NS_HSDPA, /* HSDPA only */ |
| | | NS_HSUPA, /* HSUPA only */ |
| | | NS_HSPA, /* HSDPA and HSUPA */ |
| | | }; |
| | | |
| | | typedef struct __MODULE_INFO |
| | | { |
| | | int users; /* How many users use the module now */ |
| | | unsigned char ready; /* SIM card regist and can work or not */ |
| | | unsigned char event; /* Request to set GPRS power REQ_POWER_ON, REQ_POWER_OFF or REQ_POWER_RESET */ |
| | | unsigned char pwr_status; /* Current module power status */ |
| | | |
| | | pthread_mutex_t lock; /* Module control mutex lock */ |
| | | |
| | | HW_INFO hw; /* GPRS Hardware information */ |
| | | REGISTER_INFO reg; /* SIM card register network information */ |
| | | |
| | | COM_PORT *gsmport; /* The GSM hardware UART port */ |
| | | |
| | | int comport_cnt; /* GPRS data channel count */ |
| | | COM_PORT *comport[MAX_DATAPORT]; /* CMUX driver generate CMUX port */ |
| | | } MODULE_INFO; |
| | | |
| | | |
| | | extern int init_gsm_module(MODULE_INFO *module); |
| | | extern int open_gsm_dataport(MODULE_INFO *module); |
| | | extern void close_gsm_dataport(MODULE_INFO *module); |
| | | extern COM_PORT *alloc_gsm_dataport(char *who, MODULE_INFO *module); |
| | | extern void free_gsm_dataport(char *who, MODULE_INFO *module, COM_PORT **comport); |
| | | |
| | | extern int power_on_module(MODULE_INFO *module); |
| | | extern int power_off_module(MODULE_INFO *module); |
| | | |
| | | extern int atcmd_check_ready(MODULE_INFO *module); |
| | | extern int atcmd_inspect_status(MODULE_INFO *module); |
| | | extern int atcmd_check_power_on(COM_PORT *comport); |
| | | //unsigned char atcmd_inspect(MODULE_INFO *module, COM_PORT *comport); |
| | | |
| | | extern void set_module_event(MODULE_INFO *module, int request); |
| | | extern int set_module_event_power(MODULE_INFO *module); |
| | | |
| | | extern void ctrl_thread_start(void *thread_arg); |
| | | extern void ctrl_thread_term(void *thread_arg); |
| | | |
| | | #endif /* End of __CP_GPRS_H */ |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2013 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_gsmmux.c |
| | | * Description: This file is the application for GSM0710(A.K.A CMUX) protocal |
| | | * which implement in Linux kernel |
| | | * |
| | | * Version: 1.0.0(01/16/2013~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "01/16/2013 05:37:15 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include <stdlib.h> |
| | | #include <stdio.h> |
| | | #include <string.h> |
| | | #include <sys/types.h> |
| | | #include <sys/stat.h> |
| | | #include <fcntl.h> |
| | | #include <sys/ioctl.h> |
| | | #include <errno.h> |
| | | #include <termios.h> |
| | | #include <unistd.h> |
| | | |
| | | #include "cp_logger.h" |
| | | #include "cp_gsmmux.h" |
| | | |
| | | int attach_gsm0710(COM_PORT *comport) |
| | | { |
| | | int ldisc = N_GSM0710; |
| | | struct gsm_config c; |
| | | |
| | | log_nrml("Attach GMUX on GSM port \"%s\" now\n", comport->dev_name); |
| | | |
| | | if( send_atcmd_check_ok(comport, "AT+CMUX=0\r", 3000) ) |
| | | { |
| | | log_err("Send \"AT+CMUX=0\" command check %s failure\n", comport->dev_name); |
| | | return -1; |
| | | } |
| | | |
| | | if (ioctl(comport->fd, TIOCSETD, &ldisc) < 0) |
| | | { |
| | | log_err("Can not attach N_GSM0710 to comport \"%s\" \n", comport->dev_name); |
| | | return -2; |
| | | } |
| | | |
| | | |
| | | ioctl(comport->fd, GSMIOC_GETCONF, &c); |
| | | |
| | | /* we are initiator and need encoding 0 (basic) */ |
| | | c.initiator = 1; |
| | | c.encapsulation = 0; |
| | | |
| | | /* our modem defaults to a maximum size of 127 bytes */ |
| | | c.mru = 127; |
| | | c.mtu = 127; |
| | | |
| | | /* set the new configuration */ |
| | | ioctl(comport->fd, GSMIOC_SETCONF, &c); |
| | | |
| | | log_nrml("Attach GMUX on GSM port \"%s\" OK\n", comport->dev_name); |
| | | sleep(1); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | #if 0 |
| | | int detach_gsm0710(COM_PORT *comport) |
| | | { |
| | | log_nrml("Dettach GMUX on GSM port \"%s\" now\n", comport->dev_name); |
| | | return 0; |
| | | } |
| | | #endif |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2013 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_gsmmux.h |
| | | * Description: This head file is application for GSM0710(A.K.A CMUX) protocal |
| | | * which implement in Linux kernel |
| | | * |
| | | * Version: 1.0.0(01/16/2013~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "01/16/2013 05:43:48 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #ifndef __CP_GSMMUX_H_ |
| | | #define __CP_GSMMUX_H_ |
| | | |
| | | #include "cp_atcmd.h" |
| | | |
| | | struct gsm_config |
| | | { |
| | | unsigned int adaption; |
| | | unsigned int encapsulation; |
| | | unsigned int initiator; |
| | | unsigned int t1; |
| | | unsigned int t2; |
| | | unsigned int t3; |
| | | unsigned int n2; |
| | | unsigned int mru; |
| | | unsigned int mtu; |
| | | unsigned int k; |
| | | unsigned int i; |
| | | unsigned int unused[8]; /* Padding for expansion without breaking stuff */ |
| | | }; |
| | | |
| | | #define GSMIOC_GETCONF _IOR('G', 0, struct gsm_config) |
| | | #define GSMIOC_SETCONF _IOW('G', 1, struct gsm_config) |
| | | |
| | | #define N_GSM0710 21 /* GSM 0710 Mux */ |
| | | |
| | | int attach_gsm0710(COM_PORT *comport); |
| | | //int detach_gsm0710(COM_PORT *comport); |
| | | |
| | | #endif /* __CP_GSMMUX_H_ */ |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_led_buzzer.c |
| | | * Description: This file is is the HAL(Hardware Abstraction Layer) for |
| | | * AT91SAM9xxx family devices. |
| | | * |
| | | * Version: 1.0.0(12/05/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "12/05/2012 01:26:33 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include "cp_hal.h" |
| | | |
| | | int hal_turn_led_on(int led) |
| | | { |
| | | int fd = -1; |
| | | |
| | | if((fd=open(DEV_LED_PATH, O_RDWR)) < 0) |
| | | { |
| | | return -1; |
| | | } |
| | | |
| | | ioctl(fd, LED_ON, led); |
| | | |
| | | close(fd); |
| | | return 0; |
| | | } |
| | | |
| | | int hal_turn_led_off(int led) |
| | | { |
| | | int fd = -1; |
| | | |
| | | if((fd=open(DEV_LED_PATH, O_RDWR)) < 0) |
| | | { |
| | | return -1; |
| | | } |
| | | |
| | | ioctl(fd, LED_OFF, led); |
| | | |
| | | close(fd); |
| | | return 0; |
| | | } |
| | | |
| | | int hal_turn_led_blink(int led, int mode) |
| | | { |
| | | int fd = -1; |
| | | int arg = led|(mode<<3); |
| | | |
| | | if((fd=open(DEV_LED_PATH, O_RDWR)) < 0) |
| | | { |
| | | return -1; |
| | | } |
| | | |
| | | ioctl(fd, LED_BLINK, arg); |
| | | |
| | | close(fd); |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | /* |
| | | * Description: Turn GPRS ON or OFF |
| | | * Input Args: RESET(2)/ON(1)/OFF(0) |
| | | */ |
| | | int hal_turn_gprs_power(int status) |
| | | { |
| | | int fd = -1; |
| | | int rv = 0; |
| | | |
| | | if((fd=open(DEV_GSM_PATH, O_RDWR)) < 0) |
| | | { |
| | | return -1; |
| | | } |
| | | |
| | | if( (rv=ioctl(fd, GSM_SET_POWER, status)) < 0) |
| | | { |
| | | close(fd); |
| | | return -2; |
| | | } |
| | | |
| | | close(fd); |
| | | return rv; |
| | | } |
| | | |
| | | /* |
| | | * Description: Get current GPRS power status |
| | | * Return Value: ON(1)/OFF(0) |
| | | */ |
| | | int hal_get_gprs_power(void) |
| | | { |
| | | int fd = -1; |
| | | int status; |
| | | |
| | | if((fd=open(DEV_GSM_PATH, O_RDWR)) < 0) |
| | | { |
| | | return -1; |
| | | } |
| | | |
| | | if( (status=ioctl(fd, GSM_GET_POWER, 0)) < 0) |
| | | { |
| | | close(fd); |
| | | return -2; |
| | | } |
| | | |
| | | close(fd); |
| | | return status; |
| | | } |
| | | |
| | | /* |
| | | * Description: Turn GPS ON or OFF |
| | | * Input Args: ON(1)/OFF(0) |
| | | */ |
| | | int hal_turn_gps_power(int status) |
| | | { |
| | | int fd = -1; |
| | | int rv = 0; |
| | | |
| | | if((fd=open(DEV_GPS_PATH, O_RDWR)) < 0) |
| | | { |
| | | return -1; |
| | | } |
| | | |
| | | if( (rv=ioctl(fd, GPS_SET_POWER, status)) < 0) |
| | | { |
| | | close(fd); |
| | | return -2; |
| | | } |
| | | |
| | | close(fd); |
| | | return rv; |
| | | } |
| | | |
| | | /* |
| | | * Description: Get current GPS power status |
| | | * Return Value: ON(1)/OFF(0) |
| | | */ |
| | | int hal_get_gps_power(void) |
| | | { |
| | | int fd = -1; |
| | | int status; |
| | | |
| | | if((fd=open(DEV_GPS_PATH, O_RDWR)) < 0) |
| | | { |
| | | return -1; |
| | | } |
| | | |
| | | if( (status=ioctl(fd, GPS_GET_POWER, 0)) < 0) |
| | | { |
| | | close(fd); |
| | | return -2; |
| | | } |
| | | |
| | | close(fd); |
| | | return status; |
| | | } |
| | | |
| | | |
| | | /* |
| | | * Description: Reset zigbee module |
| | | */ |
| | | int hal_reset_zigbee(void) |
| | | { |
| | | int fd = -1; |
| | | |
| | | if((fd=open(DEV_ZIGBEE_PATH, O_RDWR)) < 0) |
| | | { |
| | | return -1; |
| | | } |
| | | |
| | | if( ioctl(fd, ZIGBEE_RESET, 0) < 0) |
| | | { |
| | | close(fd); |
| | | return -2; |
| | | } |
| | | |
| | | close(fd); |
| | | return 0; |
| | | } |
| | | |
| | | /* |
| | | * Description: Get Zigbee status |
| | | */ |
| | | int hal_get_zigbee_status(void) |
| | | { |
| | | int fd = -1; |
| | | int status; |
| | | |
| | | if((fd=open(DEV_ZIGBEE_PATH, O_RDWR)) < 0) |
| | | { |
| | | return -1; |
| | | } |
| | | |
| | | if( (status=ioctl(fd, ZIGBEE_STATUS, 0)) < 0) |
| | | { |
| | | close(fd); |
| | | return -2; |
| | | } |
| | | |
| | | close(fd); |
| | | return status; |
| | | } |
| | | |
| | | /* |
| | | * Description: Start/Stop Radiation Moniter sample |
| | | * Input Args: Start(1)/Stop(0) the sample |
| | | * Return Val: If status=1(start), it will return this time sample dose |
| | | * If status=0(stop), it will return last time sample dose |
| | | */ |
| | | int hal_set_gmtube(status) |
| | | { |
| | | int fd = -1; |
| | | int dose = 0; |
| | | |
| | | if((fd=open(DEV_GMTUBE_PATH, O_RDWR)) < 0) |
| | | { |
| | | return -1; |
| | | } |
| | | |
| | | if( (dose=ioctl(fd, GM_SET_MEASURE_RADI, status)) < 0) |
| | | { |
| | | close(fd); |
| | | return -2; |
| | | } |
| | | |
| | | close(fd); |
| | | return dose; |
| | | } |
| | | |
| | | |
| | | /* |
| | | * Description: Start/Stop Radiation Moniter sample |
| | | * Input Args: Start(1)/Stop(0) the sample |
| | | * Return Val: Return last time sample dose |
| | | */ |
| | | int hal_get_gmtube_dose(void) |
| | | { |
| | | int fd = -1; |
| | | int dose = 0; |
| | | |
| | | if((fd=open(DEV_GMTUBE_PATH, O_RDWR)) < 0) |
| | | { |
| | | return -1; |
| | | } |
| | | |
| | | if( (dose=ioctl(fd, GM_GET_MEASURE_DOSE, 0)) < 0) |
| | | { |
| | | close(fd); |
| | | return -2; |
| | | } |
| | | |
| | | close(fd); |
| | | return dose; |
| | | } |
| | | |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_hal.h |
| | | * Description: This head file |
| | | * |
| | | * Version: 1.0.0(12/05/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "12/05/2012 02:21:55 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | #ifndef __CP_HAL_H |
| | | #define __CP_HAL_H |
| | | |
| | | #include <unistd.h> |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <string.h> |
| | | #include <errno.h> |
| | | #include <fcntl.h> |
| | | #include <sys/types.h> |
| | | #include <sys/stat.h> |
| | | |
| | | #include "at91_ioctl.h" |
| | | |
| | | #define DEV_LED_PATH "/dev/led" |
| | | #define DEV_GSM_PATH "/dev/gprs" |
| | | #define DEV_GPS_PATH "/dev/gps" |
| | | #define DEV_ZIGBEE_PATH "/dev/zigbee" |
| | | #define DEV_GMTUBE_PATH "/dev/gmtube" |
| | | |
| | | #define OFF 0 |
| | | #define ON 1 |
| | | #define BLINK 2 |
| | | #define RESET 2 |
| | | |
| | | #define MODE_SLOW 0 |
| | | #define MODE_FAST 1 |
| | | |
| | | #define START 1 |
| | | #define STOP 0 |
| | | |
| | | #define LED_SYS 0 |
| | | |
| | | extern int hal_turn_led_on(int led); |
| | | extern int hal_turn_led_off(int led); |
| | | extern int hal_turn_led_blink(int led, int mode); |
| | | |
| | | extern int hal_turn_gprs_power(int status); |
| | | extern int hal_get_gprs_power(void); |
| | | |
| | | extern int hal_turn_gps_power(int status); |
| | | extern int hal_get_gps_power(void); |
| | | |
| | | #endif /* Endof __CP_HAL_H */ |
New file |
| | |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @file cp_iniparser.c |
| | | @author N. Devillard |
| | | @brief Parser for ini files. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | /*---------------------------- Includes ------------------------------------*/ |
| | | #include <ctype.h> |
| | | #include "cp_iniparser.h" |
| | | |
| | | /*---------------------------- Defines -------------------------------------*/ |
| | | #define ASCIILINESZ (1024) |
| | | #define INI_INVALID_KEY ((char*)-1) |
| | | |
| | | /*--------------------------------------------------------------------------- |
| | | Private to this module |
| | | ---------------------------------------------------------------------------*/ |
| | | /** |
| | | * This enum stores the status for each parsed line (internal use only). |
| | | */ |
| | | typedef enum _line_status_ { |
| | | LINE_UNPROCESSED, |
| | | LINE_ERROR, |
| | | LINE_EMPTY, |
| | | LINE_COMMENT, |
| | | LINE_SECTION, |
| | | LINE_VALUE |
| | | } line_status ; |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Convert a string to lowercase. |
| | | @param s String to convert. |
| | | @return ptr to statically allocated string. |
| | | |
| | | This function returns a pointer to a statically allocated string |
| | | containing a lowercased version of the input string. Do not free |
| | | or modify the returned string! Since the returned string is statically |
| | | allocated, it will be modified at each function call (not re-entrant). |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | static char * strlwc(const char * s) |
| | | { |
| | | static char l[ASCIILINESZ+1]; |
| | | int i ; |
| | | |
| | | if (s==NULL) return NULL ; |
| | | memset(l, 0, ASCIILINESZ+1); |
| | | i=0 ; |
| | | while (s[i] && i<ASCIILINESZ) { |
| | | l[i] = (char)tolower((int)s[i]); |
| | | i++ ; |
| | | } |
| | | l[ASCIILINESZ]=(char)0; |
| | | return l ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Remove blanks at the beginning and the end of a string. |
| | | @param s String to parse. |
| | | @return ptr to statically allocated string. |
| | | |
| | | This function returns a pointer to a statically allocated string, |
| | | which is identical to the input string, except that all blank |
| | | characters at the end and the beg. of the string have been removed. |
| | | Do not free or modify the returned string! Since the returned string |
| | | is statically allocated, it will be modified at each function call |
| | | (not re-entrant). |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | static char * strstrip(const char * s) |
| | | { |
| | | static char l[ASCIILINESZ+1]; |
| | | char * last ; |
| | | |
| | | if (s==NULL) return NULL ; |
| | | |
| | | while (isspace((int)*s) && *s) s++; |
| | | memset(l, 0, ASCIILINESZ+1); |
| | | strcpy(l, s); |
| | | last = l + strlen(l); |
| | | while (last > l) { |
| | | if (!isspace((int)*(last-1))) |
| | | break ; |
| | | last -- ; |
| | | } |
| | | *last = (char)0; |
| | | return (char*)l ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get number of sections in a dictionary |
| | | @param d Dictionary to examine |
| | | @return int Number of sections found in dictionary |
| | | |
| | | This function returns the number of sections found in a dictionary. |
| | | The test to recognize sections is done on the string stored in the |
| | | dictionary: a section name is given as "section" whereas a key is |
| | | stored as "section:key", thus the test looks for entries that do not |
| | | contain a colon. |
| | | |
| | | This clearly fails in the case a section name contains a colon, but |
| | | this should simply be avoided. |
| | | |
| | | This function returns -1 in case of error. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int iniparser_getnsec(dictionary * d) |
| | | { |
| | | int i ; |
| | | int nsec ; |
| | | |
| | | if (d==NULL) return -1 ; |
| | | nsec=0 ; |
| | | for (i=0 ; i<d->size ; i++) { |
| | | if (d->key[i]==NULL) |
| | | continue ; |
| | | if (strchr(d->key[i], ':')==NULL) { |
| | | nsec ++ ; |
| | | } |
| | | } |
| | | return nsec ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get name for section n in a dictionary. |
| | | @param d Dictionary to examine |
| | | @param n Section number (from 0 to nsec-1). |
| | | @return Pointer to char string |
| | | |
| | | This function locates the n-th section in a dictionary and returns |
| | | its name as a pointer to a string statically allocated inside the |
| | | dictionary. Do not free or modify the returned string! |
| | | |
| | | This function returns NULL in case of error. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | char * iniparser_getsecname(dictionary * d, int n) |
| | | { |
| | | int i ; |
| | | int foundsec ; |
| | | |
| | | if (d==NULL || n<0) return NULL ; |
| | | foundsec=0 ; |
| | | for (i=0 ; i<d->size ; i++) { |
| | | if (d->key[i]==NULL) |
| | | continue ; |
| | | if (strchr(d->key[i], ':')==NULL) { |
| | | foundsec++ ; |
| | | if (foundsec>n) |
| | | break ; |
| | | } |
| | | } |
| | | if (foundsec<=n) { |
| | | return NULL ; |
| | | } |
| | | return d->key[i] ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Dump a dictionary to an opened file pointer. |
| | | @param d Dictionary to dump. |
| | | @param f Opened file pointer to dump to. |
| | | @return void |
| | | |
| | | This function prints out the contents of a dictionary, one element by |
| | | line, onto the provided file pointer. It is OK to specify @c stderr |
| | | or @c stdout as output files. This function is meant for debugging |
| | | purposes mostly. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void iniparser_dump(dictionary * d, FILE * f) |
| | | { |
| | | int i ; |
| | | |
| | | if (d==NULL || f==NULL) return ; |
| | | for (i=0 ; i<d->size ; i++) { |
| | | if (d->key[i]==NULL) |
| | | continue ; |
| | | if (d->val[i]!=NULL) { |
| | | fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]); |
| | | } else { |
| | | fprintf(f, "[%s]=UNDEF\n", d->key[i]); |
| | | } |
| | | } |
| | | return ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Save a dictionary to a loadable ini file |
| | | @param d Dictionary to dump |
| | | @param f Opened file pointer to dump to |
| | | @return void |
| | | |
| | | This function dumps a given dictionary into a loadable ini file. |
| | | It is Ok to specify @c stderr or @c stdout as output files. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void iniparser_dump_ini(dictionary * d, FILE * f) |
| | | { |
| | | int i ; |
| | | int nsec ; |
| | | char * secname ; |
| | | |
| | | if (d==NULL || f==NULL) return ; |
| | | |
| | | nsec = iniparser_getnsec(d); |
| | | if (nsec<1) { |
| | | /* No section in file: dump all keys as they are */ |
| | | for (i=0 ; i<d->size ; i++) { |
| | | if (d->key[i]==NULL) |
| | | continue ; |
| | | fprintf(f, "%s = %s\n", d->key[i], d->val[i]); |
| | | } |
| | | return ; |
| | | } |
| | | for (i=0 ; i<nsec ; i++) { |
| | | secname = iniparser_getsecname(d, i) ; |
| | | iniparser_dumpsection_ini(d, secname, f) ; |
| | | } |
| | | fprintf(f, "\n"); |
| | | return ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Save a dictionary section to a loadable ini file |
| | | @param d Dictionary to dump |
| | | @param s Section name of dictionary to dump |
| | | @param f Opened file pointer to dump to |
| | | @return void |
| | | |
| | | This function dumps a given section of a given dictionary into a loadable ini |
| | | file. It is Ok to specify @c stderr or @c stdout as output files. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void iniparser_dumpsection_ini(dictionary * d, char * s, FILE * f) |
| | | { |
| | | int j ; |
| | | char keym[ASCIILINESZ+1]; |
| | | int seclen ; |
| | | |
| | | if (d==NULL || f==NULL) return ; |
| | | if (! iniparser_find_entry(d, s)) return ; |
| | | |
| | | seclen = (int)strlen(s); |
| | | fprintf(f, "\n[%s]\n", s); |
| | | sprintf(keym, "%s:", s); |
| | | for (j=0 ; j<d->size ; j++) { |
| | | if (d->key[j]==NULL) |
| | | continue ; |
| | | if (!strncmp(d->key[j], keym, seclen+1)) { |
| | | fprintf(f, |
| | | "%-30s = %s\n", |
| | | d->key[j]+seclen+1, |
| | | d->val[j] ? d->val[j] : ""); |
| | | } |
| | | } |
| | | fprintf(f, "\n"); |
| | | return ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get the number of keys in a section of a dictionary. |
| | | @param d Dictionary to examine |
| | | @param s Section name of dictionary to examine |
| | | @return Number of keys in section |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int iniparser_getsecnkeys(dictionary * d, char * s) |
| | | { |
| | | int seclen, nkeys ; |
| | | char keym[ASCIILINESZ+1]; |
| | | int j ; |
| | | |
| | | nkeys = 0; |
| | | |
| | | if (d==NULL) return nkeys; |
| | | if (! iniparser_find_entry(d, s)) return nkeys; |
| | | |
| | | seclen = (int)strlen(s); |
| | | sprintf(keym, "%s:", s); |
| | | |
| | | for (j=0 ; j<d->size ; j++) { |
| | | if (d->key[j]==NULL) |
| | | continue ; |
| | | if (!strncmp(d->key[j], keym, seclen+1)) |
| | | nkeys++; |
| | | } |
| | | |
| | | return nkeys; |
| | | |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get the number of keys in a section of a dictionary. |
| | | @param d Dictionary to examine |
| | | @param s Section name of dictionary to examine |
| | | @return pointer to statically allocated character strings |
| | | |
| | | This function queries a dictionary and finds all keys in a given section. |
| | | Each pointer in the returned char pointer-to-pointer is pointing to |
| | | a string allocated in the dictionary; do not free or modify them. |
| | | |
| | | This function returns NULL in case of error. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | char ** iniparser_getseckeys(dictionary * d, char * s) |
| | | { |
| | | |
| | | char **keys; |
| | | |
| | | int i, j ; |
| | | char keym[ASCIILINESZ+1]; |
| | | int seclen, nkeys ; |
| | | |
| | | keys = NULL; |
| | | |
| | | if (d==NULL) return keys; |
| | | if (! iniparser_find_entry(d, s)) return keys; |
| | | |
| | | nkeys = iniparser_getsecnkeys(d, s); |
| | | |
| | | keys = (char**) malloc(nkeys*sizeof(char*)); |
| | | |
| | | seclen = (int)strlen(s); |
| | | sprintf(keym, "%s:", s); |
| | | |
| | | i = 0; |
| | | |
| | | for (j=0 ; j<d->size ; j++) { |
| | | if (d->key[j]==NULL) |
| | | continue ; |
| | | if (!strncmp(d->key[j], keym, seclen+1)) { |
| | | keys[i] = d->key[j]; |
| | | i++; |
| | | } |
| | | } |
| | | |
| | | return keys; |
| | | |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get the string associated to a key |
| | | @param d Dictionary to search |
| | | @param key Key string to look for |
| | | @param def Default value to return if key not found. |
| | | @return pointer to statically allocated character string |
| | | |
| | | This function queries a dictionary for a key. A key as read from an |
| | | ini file is given as "section:key". If the key cannot be found, |
| | | the pointer passed as 'def' is returned. |
| | | The returned char pointer is pointing to a string allocated in |
| | | the dictionary, do not free or modify it. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | char * iniparser_getstring(dictionary * d, const char * key, char * def) |
| | | { |
| | | char * lc_key ; |
| | | char * sval ; |
| | | |
| | | if (d==NULL || key==NULL) |
| | | return def ; |
| | | |
| | | lc_key = strlwc(key); |
| | | sval = dictionary_get(d, lc_key, def); |
| | | return sval ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get the string associated to a key, convert to an int |
| | | @param d Dictionary to search |
| | | @param key Key string to look for |
| | | @param notfound Value to return in case of error |
| | | @return integer |
| | | |
| | | This function queries a dictionary for a key. A key as read from an |
| | | ini file is given as "section:key". If the key cannot be found, |
| | | the notfound value is returned. |
| | | |
| | | Supported values for integers include the usual C notation |
| | | so decimal, octal (starting with 0) and hexadecimal (starting with 0x) |
| | | are supported. Examples: |
| | | |
| | | "42" -> 42 |
| | | "042" -> 34 (octal -> decimal) |
| | | "0x42" -> 66 (hexa -> decimal) |
| | | |
| | | Warning: the conversion may overflow in various ways. Conversion is |
| | | totally outsourced to strtol(), see the associated man page for overflow |
| | | handling. |
| | | |
| | | Credits: Thanks to A. Becker for suggesting strtol() |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int iniparser_getint(dictionary * d, const char * key, int notfound) |
| | | { |
| | | char * str ; |
| | | |
| | | str = iniparser_getstring(d, key, INI_INVALID_KEY); |
| | | if (str==INI_INVALID_KEY) return notfound ; |
| | | return (int)strtol(str, NULL, 0); |
| | | } |
| | | |
| | | int iniparser_getlong(dictionary * d, const char * key, int notfound) |
| | | { |
| | | char * str ; |
| | | |
| | | str = iniparser_getstring(d, key, INI_INVALID_KEY); |
| | | if (str==INI_INVALID_KEY) return notfound ; |
| | | return strtol(str, NULL, 0); |
| | | } |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get the string associated to a key, convert to a double |
| | | @param d Dictionary to search |
| | | @param key Key string to look for |
| | | @param notfound Value to return in case of error |
| | | @return double |
| | | |
| | | This function queries a dictionary for a key. A key as read from an |
| | | ini file is given as "section:key". If the key cannot be found, |
| | | the notfound value is returned. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | double iniparser_getdouble(dictionary * d, const char * key, double notfound) |
| | | { |
| | | char * str ; |
| | | |
| | | str = iniparser_getstring(d, key, INI_INVALID_KEY); |
| | | if (str==INI_INVALID_KEY) return notfound ; |
| | | return atof(str); |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get the string associated to a key, convert to a boolean |
| | | @param d Dictionary to search |
| | | @param key Key string to look for |
| | | @param notfound Value to return in case of error |
| | | @return integer |
| | | |
| | | This function queries a dictionary for a key. A key as read from an |
| | | ini file is given as "section:key". If the key cannot be found, |
| | | the notfound value is returned. |
| | | |
| | | A true boolean is found if one of the following is matched: |
| | | |
| | | - A string starting with 'y' |
| | | - A string starting with 'Y' |
| | | - A string starting with 't' |
| | | - A string starting with 'T' |
| | | - A string starting with '1' |
| | | |
| | | A false boolean is found if one of the following is matched: |
| | | |
| | | - A string starting with 'n' |
| | | - A string starting with 'N' |
| | | - A string starting with 'f' |
| | | - A string starting with 'F' |
| | | - A string starting with '0' |
| | | |
| | | The notfound value returned if no boolean is identified, does not |
| | | necessarily have to be 0 or 1. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int iniparser_getboolean(dictionary * d, const char * key, int notfound) |
| | | { |
| | | char * c ; |
| | | int ret ; |
| | | |
| | | c = iniparser_getstring(d, key, INI_INVALID_KEY); |
| | | if (c==INI_INVALID_KEY) return notfound ; |
| | | if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') { |
| | | ret = 1 ; |
| | | } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') { |
| | | ret = 0 ; |
| | | } else { |
| | | ret = notfound ; |
| | | } |
| | | return ret; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Finds out if a given entry exists in a dictionary |
| | | @param ini Dictionary to search |
| | | @param entry Name of the entry to look for |
| | | @return integer 1 if entry exists, 0 otherwise |
| | | |
| | | Finds out if a given entry exists in the dictionary. Since sections |
| | | are stored as keys with NULL associated values, this is the only way |
| | | of querying for the presence of sections in a dictionary. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int iniparser_find_entry( |
| | | dictionary * ini, |
| | | const char * entry |
| | | ) |
| | | { |
| | | int found=0 ; |
| | | if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) { |
| | | found = 1 ; |
| | | } |
| | | return found ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Set an entry in a dictionary. |
| | | @param ini Dictionary to modify. |
| | | @param entry Entry to modify (entry name) |
| | | @param val New value to associate to the entry. |
| | | @return int 0 if Ok, -1 otherwise. |
| | | |
| | | If the given entry can be found in the dictionary, it is modified to |
| | | contain the provided value. If it cannot be found, -1 is returned. |
| | | It is Ok to set val to NULL. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int iniparser_set(dictionary * ini, const char * entry, const char * val) |
| | | { |
| | | return dictionary_set(ini, strlwc(entry), val) ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Delete an entry in a dictionary |
| | | @param ini Dictionary to modify |
| | | @param entry Entry to delete (entry name) |
| | | @return void |
| | | |
| | | If the given entry can be found, it is deleted from the dictionary. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void iniparser_unset(dictionary * ini, const char * entry) |
| | | { |
| | | dictionary_unset(ini, strlwc(entry)); |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Load a single line from an INI file |
| | | @param input_line Input line, may be concatenated multi-line input |
| | | @param section Output space to store section |
| | | @param key Output space to store key |
| | | @param value Output space to store value |
| | | @return line_status value |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | static line_status iniparser_line( |
| | | char * input_line, |
| | | char * section, |
| | | char * key, |
| | | char * value) |
| | | { |
| | | line_status sta ; |
| | | char line[ASCIILINESZ+1]; |
| | | static char left_line[ASCIILINESZ+1]; |
| | | int len, offset ; |
| | | |
| | | strcpy(line, strstrip(input_line)); |
| | | len = (int)strlen(line); |
| | | |
| | | sta = LINE_UNPROCESSED ; |
| | | if (len<1) { |
| | | /* Empty line */ |
| | | sta = LINE_EMPTY ; |
| | | memset(input_line, 0, len); |
| | | } else if (line[0]=='#' || line[0]==';') { |
| | | /* Comment line */ |
| | | sta = LINE_COMMENT ; |
| | | memset(input_line, 0, len); |
| | | } else if (line[0]=='[') { |
| | | /* Section name */ |
| | | sscanf(line, "[%[^]]", section); |
| | | strcpy(section, strstrip(section)); |
| | | strcpy(section, strlwc(section)); |
| | | |
| | | /* Left configure will go to next time to parser */ |
| | | offset = strlen(section) + 2; |
| | | strcpy( left_line, strstrip(&(line[offset])) ); |
| | | strcpy( left_line, strstrip(left_line)); |
| | | |
| | | if( strlen(left_line) > 0) |
| | | { |
| | | strcpy(input_line, left_line); |
| | | strcat(input_line, "\n"); |
| | | } |
| | | else |
| | | { |
| | | memset(input_line, 0, len); |
| | | } |
| | | sta = LINE_SECTION ; |
| | | } else if (sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2 |
| | | || sscanf (line, "%[^=] = '%[^\']'", key, value) == 2 |
| | | || sscanf (line, "%[^=] = %[^;#]", key, value) == 2) { |
| | | char *ptr = NULL; |
| | | |
| | | /* Usual key=value, with or without comments */ |
| | | strcpy(key, strstrip(key)); |
| | | strcpy(key, strlwc(key)); |
| | | strcpy(value, strstrip(value)); |
| | | /* |
| | | * sscanf cannot handle '' or "" as empty values |
| | | * this is done here |
| | | */ |
| | | if (!strncmp(value, "\"\"", 2) || (!strncmp(value, "''", 2)) ) { |
| | | value[0]=0 ; |
| | | } |
| | | |
| | | ptr = strchr(line, '='); |
| | | if('\''==*(ptr+1) || '\"'==*(ptr+1)) |
| | | { |
| | | offset = strlen(key)+strlen(value) + 1 + 2; /* Skip $key='$val' */ |
| | | } |
| | | else |
| | | { |
| | | offset = strlen(key)+strlen(value) + 1; /* Skip $key=$val */ |
| | | } |
| | | strcpy( left_line, strstrip(&(line[offset])) ); |
| | | |
| | | if( strlen(left_line) > 0) |
| | | { |
| | | strcpy(input_line, left_line); |
| | | strcat(input_line, "\n"); |
| | | } |
| | | else |
| | | { |
| | | memset(input_line, 0, len); |
| | | } |
| | | sta = LINE_VALUE ; |
| | | } else if (sscanf(line, "%[^=] = %[;#]", key, value)==2 |
| | | || sscanf(line, "%[^=] %[=]", key, value) == 2) { |
| | | /* |
| | | * Special cases: |
| | | * key= |
| | | * key=; |
| | | * key=# |
| | | */ |
| | | strcpy(key, strstrip(key)); |
| | | strcpy(key, strlwc(key)); |
| | | value[0]=0 ; |
| | | sta = LINE_VALUE ; |
| | | } else { |
| | | /* Generate syntax error */ |
| | | sta = LINE_ERROR ; |
| | | memset(input_line, 0, len); |
| | | } |
| | | return sta ; |
| | | } |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Parse an ini file and return an allocated dictionary object |
| | | @param ininame Name of the ini file to read. |
| | | @return Pointer to newly allocated dictionary |
| | | |
| | | This is the parser for ini files. This function is called, providing |
| | | the name of the file to be read. It returns a dictionary object that |
| | | should not be accessed directly, but through accessor functions |
| | | instead. |
| | | |
| | | The returned dictionary must be freed using iniparser_freedict(). |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | dictionary * iniparser_load(const char * ininame) |
| | | { |
| | | FILE * in ; |
| | | |
| | | char line [ASCIILINESZ+1] ; |
| | | char section [ASCIILINESZ+1] ; |
| | | char key [ASCIILINESZ+1] ; |
| | | char tmp [ASCIILINESZ+1] ; |
| | | char val [ASCIILINESZ+1] ; |
| | | |
| | | int last=0 ; |
| | | int len ; |
| | | int lineno=0 ; |
| | | int errs=0; |
| | | |
| | | dictionary * dict ; |
| | | |
| | | if ((in=fopen(ininame, "r"))==NULL) { |
| | | fprintf(stderr, "iniparser: cannot open %s\n", ininame); |
| | | return NULL ; |
| | | } |
| | | |
| | | dict = dictionary_new(0) ; |
| | | if (!dict) { |
| | | fclose(in); |
| | | return NULL ; |
| | | } |
| | | |
| | | memset(line, 0, ASCIILINESZ); |
| | | memset(section, 0, ASCIILINESZ); |
| | | memset(key, 0, ASCIILINESZ); |
| | | memset(val, 0, ASCIILINESZ); |
| | | last=0 ; |
| | | |
| | | while (fgets(line+last, ASCIILINESZ-last, in)!=NULL) { |
| | | lineno++ ; |
| | | CONTINUE_PARSER: |
| | | len = (int)strlen(line)-1; |
| | | if (len==0) |
| | | continue; |
| | | /* Safety check against buffer overflows */ |
| | | if (line[len]!='\n') { |
| | | fprintf(stderr, |
| | | "iniparser: input line too long in %s (%d)\n", |
| | | ininame, |
| | | lineno); |
| | | dictionary_del(dict); |
| | | fclose(in); |
| | | return NULL ; |
| | | } |
| | | /* Get rid of \n and spaces at end of line */ |
| | | while ((len>=0) && |
| | | ((line[len]=='\n') || (isspace(line[len])))) { |
| | | line[len]=0 ; |
| | | len-- ; |
| | | } |
| | | /* Detect multi-line */ |
| | | if (line[len]=='\\') { |
| | | /* Multi-line value */ |
| | | last=len ; |
| | | continue ; |
| | | } else { |
| | | last=0 ; |
| | | } |
| | | |
| | | switch ( iniparser_line(line, section, key, val) ) { |
| | | case LINE_EMPTY: |
| | | case LINE_COMMENT: |
| | | break ; |
| | | |
| | | case LINE_SECTION: |
| | | errs = dictionary_set(dict, section, NULL); |
| | | break ; |
| | | |
| | | case LINE_VALUE: |
| | | sprintf(tmp, "%s:%s", section, key); |
| | | errs = dictionary_set(dict, tmp, val) ; |
| | | break ; |
| | | |
| | | case LINE_ERROR: |
| | | fprintf(stderr, "iniparser: syntax error in %s (%d):\n", |
| | | ininame, |
| | | lineno); |
| | | fprintf(stderr, "-> %s\n", line); |
| | | errs++ ; |
| | | break; |
| | | |
| | | default: |
| | | break ; |
| | | } |
| | | |
| | | if( strlen(line) > 0) |
| | | { |
| | | goto CONTINUE_PARSER; |
| | | } |
| | | |
| | | memset(line, 0, ASCIILINESZ); |
| | | last=0; |
| | | if (errs<0) { |
| | | fprintf(stderr, "iniparser: memory allocation failure\n"); |
| | | break ; |
| | | } |
| | | } |
| | | if (errs) { |
| | | dictionary_del(dict); |
| | | dict = NULL ; |
| | | } |
| | | fclose(in); |
| | | return dict ; |
| | | } |
| | | |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Free all memory associated to an ini dictionary |
| | | @param d Dictionary to free |
| | | @return void |
| | | |
| | | Free all memory associated to an ini dictionary. |
| | | It is mandatory to call this function before the dictionary object |
| | | gets out of the current context. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void iniparser_freedict(dictionary * d) |
| | | { |
| | | dictionary_del(d); |
| | | } |
| | | |
| | | /* vim: set ts=4 et sw=4 tw=75 */ |
New file |
| | |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @file cp_iniparser.h |
| | | @author N. Devillard |
| | | @brief Parser for ini files. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | |
| | | #ifndef _CP_INIPARSER_H_ |
| | | #define _CP_INIPARSER_H_ |
| | | |
| | | /*--------------------------------------------------------------------------- |
| | | Includes |
| | | ---------------------------------------------------------------------------*/ |
| | | |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <string.h> |
| | | |
| | | /* |
| | | * The following #include is necessary on many Unixes but not Linux. |
| | | * It is not needed for Windows platforms. |
| | | * Uncomment it if needed. |
| | | */ |
| | | /* #include <unistd.h> */ |
| | | |
| | | #include "cp_dictionary.h" |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get number of sections in a dictionary |
| | | @param d Dictionary to examine |
| | | @return int Number of sections found in dictionary |
| | | |
| | | This function returns the number of sections found in a dictionary. |
| | | The test to recognize sections is done on the string stored in the |
| | | dictionary: a section name is given as "section" whereas a key is |
| | | stored as "section:key", thus the test looks for entries that do not |
| | | contain a colon. |
| | | |
| | | This clearly fails in the case a section name contains a colon, but |
| | | this should simply be avoided. |
| | | |
| | | This function returns -1 in case of error. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | |
| | | int iniparser_getnsec(dictionary * d); |
| | | |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get name for section n in a dictionary. |
| | | @param d Dictionary to examine |
| | | @param n Section number (from 0 to nsec-1). |
| | | @return Pointer to char string |
| | | |
| | | This function locates the n-th section in a dictionary and returns |
| | | its name as a pointer to a string statically allocated inside the |
| | | dictionary. Do not free or modify the returned string! |
| | | |
| | | This function returns NULL in case of error. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | |
| | | char * iniparser_getsecname(dictionary * d, int n); |
| | | |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Save a dictionary to a loadable ini file |
| | | @param d Dictionary to dump |
| | | @param f Opened file pointer to dump to |
| | | @return void |
| | | |
| | | This function dumps a given dictionary into a loadable ini file. |
| | | It is Ok to specify @c stderr or @c stdout as output files. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | |
| | | void iniparser_dump_ini(dictionary * d, FILE * f); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Save a dictionary section to a loadable ini file |
| | | @param d Dictionary to dump |
| | | @param s Section name of dictionary to dump |
| | | @param f Opened file pointer to dump to |
| | | @return void |
| | | |
| | | This function dumps a given section of a given dictionary into a loadable ini |
| | | file. It is Ok to specify @c stderr or @c stdout as output files. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | |
| | | void iniparser_dumpsection_ini(dictionary * d, char * s, FILE * f); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Dump a dictionary to an opened file pointer. |
| | | @param d Dictionary to dump. |
| | | @param f Opened file pointer to dump to. |
| | | @return void |
| | | |
| | | This function prints out the contents of a dictionary, one element by |
| | | line, onto the provided file pointer. It is OK to specify @c stderr |
| | | or @c stdout as output files. This function is meant for debugging |
| | | purposes mostly. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void iniparser_dump(dictionary * d, FILE * f); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get the number of keys in a section of a dictionary. |
| | | @param d Dictionary to examine |
| | | @param s Section name of dictionary to examine |
| | | @return Number of keys in section |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int iniparser_getsecnkeys(dictionary * d, char * s); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get the number of keys in a section of a dictionary. |
| | | @param d Dictionary to examine |
| | | @param s Section name of dictionary to examine |
| | | @return pointer to statically allocated character strings |
| | | |
| | | This function queries a dictionary and finds all keys in a given section. |
| | | Each pointer in the returned char pointer-to-pointer is pointing to |
| | | a string allocated in the dictionary; do not free or modify them. |
| | | |
| | | This function returns NULL in case of error. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | char ** iniparser_getseckeys(dictionary * d, char * s); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get the string associated to a key |
| | | @param d Dictionary to search |
| | | @param key Key string to look for |
| | | @param def Default value to return if key not found. |
| | | @return pointer to statically allocated character string |
| | | |
| | | This function queries a dictionary for a key. A key as read from an |
| | | ini file is given as "section:key". If the key cannot be found, |
| | | the pointer passed as 'def' is returned. |
| | | The returned char pointer is pointing to a string allocated in |
| | | the dictionary, do not free or modify it. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | char * iniparser_getstring(dictionary * d, const char * key, char * def); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get the string associated to a key, convert to an int |
| | | @param d Dictionary to search |
| | | @param key Key string to look for |
| | | @param notfound Value to return in case of error |
| | | @return integer |
| | | |
| | | This function queries a dictionary for a key. A key as read from an |
| | | ini file is given as "section:key". If the key cannot be found, |
| | | the notfound value is returned. |
| | | |
| | | Supported values for integers include the usual C notation |
| | | so decimal, octal (starting with 0) and hexadecimal (starting with 0x) |
| | | are supported. Examples: |
| | | |
| | | - "42" -> 42 |
| | | - "042" -> 34 (octal -> decimal) |
| | | - "0x42" -> 66 (hexa -> decimal) |
| | | |
| | | Warning: the conversion may overflow in various ways. Conversion is |
| | | totally outsourced to strtol(), see the associated man page for overflow |
| | | handling. |
| | | |
| | | Credits: Thanks to A. Becker for suggesting strtol() |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int iniparser_getint(dictionary * d, const char * key, int notfound); |
| | | int iniparser_getlong(dictionary * d, const char * key, int notfound); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get the string associated to a key, convert to a double |
| | | @param d Dictionary to search |
| | | @param key Key string to look for |
| | | @param notfound Value to return in case of error |
| | | @return double |
| | | |
| | | This function queries a dictionary for a key. A key as read from an |
| | | ini file is given as "section:key". If the key cannot be found, |
| | | the notfound value is returned. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | double iniparser_getdouble(dictionary * d, const char * key, double notfound); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Get the string associated to a key, convert to a boolean |
| | | @param d Dictionary to search |
| | | @param key Key string to look for |
| | | @param notfound Value to return in case of error |
| | | @return integer |
| | | |
| | | This function queries a dictionary for a key. A key as read from an |
| | | ini file is given as "section:key". If the key cannot be found, |
| | | the notfound value is returned. |
| | | |
| | | A true boolean is found if one of the following is matched: |
| | | |
| | | - A string starting with 'y' |
| | | - A string starting with 'Y' |
| | | - A string starting with 't' |
| | | - A string starting with 'T' |
| | | - A string starting with '1' |
| | | |
| | | A false boolean is found if one of the following is matched: |
| | | |
| | | - A string starting with 'n' |
| | | - A string starting with 'N' |
| | | - A string starting with 'f' |
| | | - A string starting with 'F' |
| | | - A string starting with '0' |
| | | |
| | | The notfound value returned if no boolean is identified, does not |
| | | necessarily have to be 0 or 1. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int iniparser_getboolean(dictionary * d, const char * key, int notfound); |
| | | |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Set an entry in a dictionary. |
| | | @param ini Dictionary to modify. |
| | | @param entry Entry to modify (entry name) |
| | | @param val New value to associate to the entry. |
| | | @return int 0 if Ok, -1 otherwise. |
| | | |
| | | If the given entry can be found in the dictionary, it is modified to |
| | | contain the provided value. If it cannot be found, -1 is returned. |
| | | It is Ok to set val to NULL. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int iniparser_set(dictionary * ini, const char * entry, const char * val); |
| | | |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Delete an entry in a dictionary |
| | | @param ini Dictionary to modify |
| | | @param entry Entry to delete (entry name) |
| | | @return void |
| | | |
| | | If the given entry can be found, it is deleted from the dictionary. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void iniparser_unset(dictionary * ini, const char * entry); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Finds out if a given entry exists in a dictionary |
| | | @param ini Dictionary to search |
| | | @param entry Name of the entry to look for |
| | | @return integer 1 if entry exists, 0 otherwise |
| | | |
| | | Finds out if a given entry exists in the dictionary. Since sections |
| | | are stored as keys with NULL associated values, this is the only way |
| | | of querying for the presence of sections in a dictionary. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | int iniparser_find_entry(dictionary * ini, const char * entry) ; |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Parse an ini file and return an allocated dictionary object |
| | | @param ininame Name of the ini file to read. |
| | | @return Pointer to newly allocated dictionary |
| | | |
| | | This is the parser for ini files. This function is called, providing |
| | | the name of the file to be read. It returns a dictionary object that |
| | | should not be accessed directly, but through accessor functions |
| | | instead. |
| | | |
| | | The returned dictionary must be freed using iniparser_freedict(). |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | dictionary * iniparser_load(const char * ininame); |
| | | |
| | | /*-------------------------------------------------------------------------*/ |
| | | /** |
| | | @brief Free all memory associated to an ini dictionary |
| | | @param d Dictionary to free |
| | | @return void |
| | | |
| | | Free all memory associated to an ini dictionary. |
| | | It is mandatory to call this function before the dictionary object |
| | | gets out of the current context. |
| | | */ |
| | | /*--------------------------------------------------------------------------*/ |
| | | void iniparser_freedict(dictionary * d); |
| | | |
| | | #endif |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue <guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_list.h |
| | | * Description: This file is copied from Linux kernel, which provide link list API. |
| | | * |
| | | * Version: 1.0.0(08/09/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "08/09/2012 02:24:34 AM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #ifndef _LINUX_LIST_H |
| | | #define _LINUX_LIST_H |
| | | |
| | | #include <linux/stddef.h> |
| | | |
| | | |
| | | /** |
| | | * container_of - cast a member of a structure out to the containing structure |
| | | * @ptr: the pointer to the member. |
| | | * @type: the type of the container struct this is embedded in. |
| | | * @member: the name of the member within the struct. |
| | | * |
| | | */ |
| | | #undef offsetof |
| | | #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) |
| | | #define container_of(ptr, type, member) ({ \ |
| | | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ |
| | | (type *)( (char *)__mptr - offsetof(type,member) );}) |
| | | |
| | | |
| | | /* |
| | | * Architectures might want to move the poison pointer offset |
| | | * into some well-recognized area such as 0xdead000000000000, |
| | | * that is also not mappable by user-space exploits: |
| | | */ |
| | | #ifdef CONFIG_ILLEGAL_POINTER_VALUE |
| | | # define POISON_POINTER_DELTA _AC(CONFIG_ILLEGAL_POINTER_VALUE, UL) |
| | | #else |
| | | # define POISON_POINTER_DELTA 0 |
| | | #endif |
| | | |
| | | /* |
| | | * These are non-NULL pointers that will result in page faults |
| | | * under normal circumstances, used to verify that nobody uses |
| | | * non-initialized list entries. |
| | | */ |
| | | #define LIST_POISON1 ((void *) 0x00100100 + POISON_POINTER_DELTA) |
| | | #define LIST_POISON2 ((void *) 0x00200200 + POISON_POINTER_DELTA) |
| | | |
| | | #ifndef ARCH_HAS_PREFETCH |
| | | #define ARCH_HAS_PREFETCH |
| | | static inline void prefetch(const void *x) {;} |
| | | #endif |
| | | |
| | | /* |
| | | * Simple doubly linked list implementation. |
| | | * |
| | | * Some of the internal functions ("__xxx") are useful when |
| | | * manipulating whole lists rather than single entries, as |
| | | * sometimes we already know the next/prev entries and we can |
| | | * generate better code by using them directly rather than |
| | | * using the generic single-entry routines. |
| | | */ |
| | | |
| | | struct list_head { |
| | | struct list_head *next, *prev; |
| | | }; |
| | | |
| | | #define LIST_HEAD_INIT(name) { &(name), &(name) } |
| | | |
| | | #define LIST_HEAD(name) \ |
| | | struct list_head name = LIST_HEAD_INIT(name) |
| | | |
| | | static inline void INIT_LIST_HEAD(struct list_head *list) |
| | | { |
| | | list->next = list; |
| | | list->prev = list; |
| | | } |
| | | |
| | | /* |
| | | * Insert a new entry between two known consecutive entries. |
| | | * |
| | | * This is only for internal list manipulation where we know |
| | | * the prev/next entries already! |
| | | */ |
| | | static inline void __list_add(struct list_head *new, |
| | | struct list_head *prev, |
| | | struct list_head *next) |
| | | { |
| | | next->prev = new; |
| | | new->next = next; |
| | | new->prev = prev; |
| | | prev->next = new; |
| | | } |
| | | |
| | | /** |
| | | * list_add - add a new entry |
| | | * @new: new entry to be added |
| | | * @head: list head to add it after |
| | | * |
| | | * Insert a new entry after the specified head. |
| | | * This is good for implementing stacks. |
| | | */ |
| | | static inline void list_add(struct list_head *new, struct list_head *head) |
| | | { |
| | | __list_add(new, head, head->next); |
| | | } |
| | | |
| | | /** |
| | | * list_add_tail - add a new entry |
| | | * @new: new entry to be added |
| | | * @head: list head to add it before |
| | | * |
| | | * Insert a new entry before the specified head. |
| | | * This is useful for implementing queues. |
| | | */ |
| | | static inline void list_add_tail(struct list_head *new, struct list_head *head) |
| | | { |
| | | __list_add(new, head->prev, head); |
| | | } |
| | | |
| | | /* |
| | | * Delete a list entry by making the prev/next entries |
| | | * point to each other. |
| | | * |
| | | * This is only for internal list manipulation where we know |
| | | * the prev/next entries already! |
| | | */ |
| | | static inline void __list_del(struct list_head *prev, struct list_head *next) |
| | | { |
| | | next->prev = prev; |
| | | prev->next = next; |
| | | } |
| | | |
| | | /** |
| | | * list_del - deletes entry from list. |
| | | * @entry: the element to delete from the list. |
| | | * Note: list_empty() on entry does not return true after this, the entry is |
| | | * in an undefined state. |
| | | */ |
| | | static inline void list_del(struct list_head *entry) |
| | | { |
| | | __list_del(entry->prev, entry->next); |
| | | entry->next = LIST_POISON1; |
| | | entry->prev = LIST_POISON2; |
| | | } |
| | | |
| | | /** |
| | | * list_replace - replace old entry by new one |
| | | * @old : the element to be replaced |
| | | * @new : the new element to insert |
| | | * |
| | | * If @old was empty, it will be overwritten. |
| | | */ |
| | | static inline void list_replace(struct list_head *old, |
| | | struct list_head *new) |
| | | { |
| | | new->next = old->next; |
| | | new->next->prev = new; |
| | | new->prev = old->prev; |
| | | new->prev->next = new; |
| | | } |
| | | |
| | | static inline void list_replace_init(struct list_head *old, |
| | | struct list_head *new) |
| | | { |
| | | list_replace(old, new); |
| | | INIT_LIST_HEAD(old); |
| | | } |
| | | |
| | | /** |
| | | * list_del_init - deletes entry from list and reinitialize it. |
| | | * @entry: the element to delete from the list. |
| | | */ |
| | | static inline void list_del_init(struct list_head *entry) |
| | | { |
| | | __list_del(entry->prev, entry->next); |
| | | INIT_LIST_HEAD(entry); |
| | | } |
| | | |
| | | /** |
| | | * list_move - delete from one list and add as another's head |
| | | * @list: the entry to move |
| | | * @head: the head that will precede our entry |
| | | */ |
| | | static inline void list_move(struct list_head *list, struct list_head *head) |
| | | { |
| | | __list_del(list->prev, list->next); |
| | | list_add(list, head); |
| | | } |
| | | |
| | | /** |
| | | * list_move_tail - delete from one list and add as another's tail |
| | | * @list: the entry to move |
| | | * @head: the head that will follow our entry |
| | | */ |
| | | static inline void list_move_tail(struct list_head *list, |
| | | struct list_head *head) |
| | | { |
| | | __list_del(list->prev, list->next); |
| | | list_add_tail(list, head); |
| | | } |
| | | |
| | | /** |
| | | * list_is_last - tests whether @list is the last entry in list @head |
| | | * @list: the entry to test |
| | | * @head: the head of the list |
| | | */ |
| | | static inline int list_is_last(const struct list_head *list, |
| | | const struct list_head *head) |
| | | { |
| | | return list->next == head; |
| | | } |
| | | |
| | | /** |
| | | * list_empty - tests whether a list is empty |
| | | * @head: the list to test. |
| | | */ |
| | | static inline int list_empty(const struct list_head *head) |
| | | { |
| | | return head->next == head; |
| | | } |
| | | |
| | | /** |
| | | * list_empty_careful - tests whether a list is empty and not being modified |
| | | * @head: the list to test |
| | | * |
| | | * Description: |
| | | * tests whether a list is empty _and_ checks that no other CPU might be |
| | | * in the process of modifying either member (next or prev) |
| | | * |
| | | * NOTE: using list_empty_careful() without synchronization |
| | | * can only be safe if the only activity that can happen |
| | | * to the list entry is list_del_init(). Eg. it cannot be used |
| | | * if another CPU could re-list_add() it. |
| | | */ |
| | | static inline int list_empty_careful(const struct list_head *head) |
| | | { |
| | | struct list_head *next = head->next; |
| | | return (next == head) && (next == head->prev); |
| | | } |
| | | |
| | | /** |
| | | * list_is_singular - tests whether a list has just one entry. |
| | | * @head: the list to test. |
| | | */ |
| | | static inline int list_is_singular(const struct list_head *head) |
| | | { |
| | | return !list_empty(head) && (head->next == head->prev); |
| | | } |
| | | |
| | | static inline void __list_cut_position(struct list_head *list, |
| | | struct list_head *head, struct list_head *entry) |
| | | { |
| | | struct list_head *new_first = entry->next; |
| | | list->next = head->next; |
| | | list->next->prev = list; |
| | | list->prev = entry; |
| | | entry->next = list; |
| | | head->next = new_first; |
| | | new_first->prev = head; |
| | | } |
| | | |
| | | /** |
| | | * list_cut_position - cut a list into two |
| | | * @list: a new list to add all removed entries |
| | | * @head: a list with entries |
| | | * @entry: an entry within head, could be the head itself |
| | | * and if so we won't cut the list |
| | | * |
| | | * This helper moves the initial part of @head, up to and |
| | | * including @entry, from @head to @list. You should |
| | | * pass on @entry an element you know is on @head. @list |
| | | * should be an empty list or a list you do not care about |
| | | * losing its data. |
| | | * |
| | | */ |
| | | static inline void list_cut_position(struct list_head *list, |
| | | struct list_head *head, struct list_head *entry) |
| | | { |
| | | if (list_empty(head)) |
| | | return; |
| | | if (list_is_singular(head) && |
| | | (head->next != entry && head != entry)) |
| | | return; |
| | | if (entry == head) |
| | | INIT_LIST_HEAD(list); |
| | | else |
| | | __list_cut_position(list, head, entry); |
| | | } |
| | | |
| | | static inline void __list_splice(const struct list_head *list, |
| | | struct list_head *prev, |
| | | struct list_head *next) |
| | | { |
| | | struct list_head *first = list->next; |
| | | struct list_head *last = list->prev; |
| | | |
| | | first->prev = prev; |
| | | prev->next = first; |
| | | |
| | | last->next = next; |
| | | next->prev = last; |
| | | } |
| | | |
| | | /** |
| | | * list_splice - join two lists, this is designed for stacks |
| | | * @list: the new list to add. |
| | | * @head: the place to add it in the first list. |
| | | */ |
| | | static inline void list_splice(const struct list_head *list, |
| | | struct list_head *head) |
| | | { |
| | | if (!list_empty(list)) |
| | | __list_splice(list, head, head->next); |
| | | } |
| | | |
| | | /** |
| | | * list_splice_tail - join two lists, each list being a queue |
| | | * @list: the new list to add. |
| | | * @head: the place to add it in the first list. |
| | | */ |
| | | static inline void list_splice_tail(struct list_head *list, |
| | | struct list_head *head) |
| | | { |
| | | if (!list_empty(list)) |
| | | __list_splice(list, head->prev, head); |
| | | } |
| | | |
| | | /** |
| | | * list_splice_init - join two lists and reinitialise the emptied list. |
| | | * @list: the new list to add. |
| | | * @head: the place to add it in the first list. |
| | | * |
| | | * The list at @list is reinitialised |
| | | */ |
| | | static inline void list_splice_init(struct list_head *list, |
| | | struct list_head *head) |
| | | { |
| | | if (!list_empty(list)) { |
| | | __list_splice(list, head, head->next); |
| | | INIT_LIST_HEAD(list); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * list_splice_tail_init - join two lists and reinitialise the emptied list |
| | | * @list: the new list to add. |
| | | * @head: the place to add it in the first list. |
| | | * |
| | | * Each of the lists is a queue. |
| | | * The list at @list is reinitialised |
| | | */ |
| | | static inline void list_splice_tail_init(struct list_head *list, |
| | | struct list_head *head) |
| | | { |
| | | if (!list_empty(list)) { |
| | | __list_splice(list, head->prev, head); |
| | | INIT_LIST_HEAD(list); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * list_entry - get the struct for this entry |
| | | * @ptr: the &struct list_head pointer. |
| | | * @type: the type of the struct this is embedded in. |
| | | * @member: the name of the list_struct within the struct. |
| | | */ |
| | | #define list_entry(ptr, type, member) \ |
| | | container_of(ptr, type, member) |
| | | |
| | | /** |
| | | * list_first_entry - get the first element from a list |
| | | * @ptr: the list head to take the element from. |
| | | * @type: the type of the struct this is embedded in. |
| | | * @member: the name of the list_struct within the struct. |
| | | * |
| | | * Note, that list is expected to be not empty. |
| | | */ |
| | | #define list_first_entry(ptr, type, member) \ |
| | | list_entry((ptr)->next, type, member) |
| | | |
| | | /** |
| | | * list_for_each - iterate over a list |
| | | * @pos: the &struct list_head to use as a loop cursor. |
| | | * @head: the head for your list. |
| | | */ |
| | | #define list_for_each(pos, head) \ |
| | | for (pos = (head)->next; prefetch(pos->next), pos != (head); \ |
| | | pos = pos->next) |
| | | |
| | | /** |
| | | * __list_for_each - iterate over a list |
| | | * @pos: the &struct list_head to use as a loop cursor. |
| | | * @head: the head for your list. |
| | | * |
| | | * This variant differs from list_for_each() in that it's the |
| | | * simplest possible list iteration code, no prefetching is done. |
| | | * Use this for code that knows the list to be very short (empty |
| | | * or 1 entry) most of the time. |
| | | */ |
| | | #define __list_for_each(pos, head) \ |
| | | for (pos = (head)->next; pos != (head); pos = pos->next) |
| | | |
| | | /** |
| | | * list_for_each_prev - iterate over a list backwards |
| | | * @pos: the &struct list_head to use as a loop cursor. |
| | | * @head: the head for your list. |
| | | */ |
| | | #define list_for_each_prev(pos, head) \ |
| | | for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \ |
| | | pos = pos->prev) |
| | | |
| | | /** |
| | | * list_for_each_safe - iterate over a list safe against removal of list entry |
| | | * @pos: the &struct list_head to use as a loop cursor. |
| | | * @n: another &struct list_head to use as temporary storage |
| | | * @head: the head for your list. |
| | | */ |
| | | #define list_for_each_safe(pos, n, head) \ |
| | | for (pos = (head)->next, n = pos->next; pos != (head); \ |
| | | pos = n, n = pos->next) |
| | | |
| | | /** |
| | | * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry |
| | | * @pos: the &struct list_head to use as a loop cursor. |
| | | * @n: another &struct list_head to use as temporary storage |
| | | * @head: the head for your list. |
| | | */ |
| | | #define list_for_each_prev_safe(pos, n, head) \ |
| | | for (pos = (head)->prev, n = pos->prev; \ |
| | | prefetch(pos->prev), pos != (head); \ |
| | | pos = n, n = pos->prev) |
| | | |
| | | /** |
| | | * list_for_each_entry - iterate over list of given type |
| | | * @pos: the type * to use as a loop cursor. |
| | | * @head: the head for your list. |
| | | * @member: the name of the list_struct within the struct. |
| | | */ |
| | | #define list_for_each_entry(pos, head, member) \ |
| | | for (pos = list_entry((head)->next, typeof(*pos), member); \ |
| | | prefetch(pos->member.next), &pos->member != (head); \ |
| | | pos = list_entry(pos->member.next, typeof(*pos), member)) |
| | | |
| | | /** |
| | | * list_for_each_entry_reverse - iterate backwards over list of given type. |
| | | * @pos: the type * to use as a loop cursor. |
| | | * @head: the head for your list. |
| | | * @member: the name of the list_struct within the struct. |
| | | */ |
| | | #define list_for_each_entry_reverse(pos, head, member) \ |
| | | for (pos = list_entry((head)->prev, typeof(*pos), member); \ |
| | | prefetch(pos->member.prev), &pos->member != (head); \ |
| | | pos = list_entry(pos->member.prev, typeof(*pos), member)) |
| | | |
| | | /** |
| | | * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue() |
| | | * @pos: the type * to use as a start point |
| | | * @head: the head of the list |
| | | * @member: the name of the list_struct within the struct. |
| | | * |
| | | * Prepares a pos entry for use as a start point in list_for_each_entry_continue(). |
| | | */ |
| | | #define list_prepare_entry(pos, head, member) \ |
| | | ((pos) ? : list_entry(head, typeof(*pos), member)) |
| | | |
| | | /** |
| | | * list_for_each_entry_continue - continue iteration over list of given type |
| | | * @pos: the type * to use as a loop cursor. |
| | | * @head: the head for your list. |
| | | * @member: the name of the list_struct within the struct. |
| | | * |
| | | * Continue to iterate over list of given type, continuing after |
| | | * the current position. |
| | | */ |
| | | #define list_for_each_entry_continue(pos, head, member) \ |
| | | for (pos = list_entry(pos->member.next, typeof(*pos), member); \ |
| | | prefetch(pos->member.next), &pos->member != (head); \ |
| | | pos = list_entry(pos->member.next, typeof(*pos), member)) |
| | | |
| | | /** |
| | | * list_for_each_entry_continue_reverse - iterate backwards from the given point |
| | | * @pos: the type * to use as a loop cursor. |
| | | * @head: the head for your list. |
| | | * @member: the name of the list_struct within the struct. |
| | | * |
| | | * Start to iterate over list of given type backwards, continuing after |
| | | * the current position. |
| | | */ |
| | | #define list_for_each_entry_continue_reverse(pos, head, member) \ |
| | | for (pos = list_entry(pos->member.prev, typeof(*pos), member); \ |
| | | prefetch(pos->member.prev), &pos->member != (head); \ |
| | | pos = list_entry(pos->member.prev, typeof(*pos), member)) |
| | | |
| | | /** |
| | | * list_for_each_entry_from - iterate over list of given type from the current point |
| | | * @pos: the type * to use as a loop cursor. |
| | | * @head: the head for your list. |
| | | * @member: the name of the list_struct within the struct. |
| | | * |
| | | * Iterate over list of given type, continuing from current position. |
| | | */ |
| | | #define list_for_each_entry_from(pos, head, member) \ |
| | | for (; prefetch(pos->member.next), &pos->member != (head); \ |
| | | pos = list_entry(pos->member.next, typeof(*pos), member)) |
| | | |
| | | /** |
| | | * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry |
| | | * @pos: the type * to use as a loop cursor. |
| | | * @n: another type * to use as temporary storage |
| | | * @head: the head for your list. |
| | | * @member: the name of the list_struct within the struct. |
| | | */ |
| | | #define list_for_each_entry_safe(pos, n, head, member) \ |
| | | for (pos = list_entry((head)->next, typeof(*pos), member), \ |
| | | n = list_entry(pos->member.next, typeof(*pos), member); \ |
| | | &pos->member != (head); \ |
| | | pos = n, n = list_entry(n->member.next, typeof(*n), member)) |
| | | |
| | | /** |
| | | * list_for_each_entry_safe_continue |
| | | * @pos: the type * to use as a loop cursor. |
| | | * @n: another type * to use as temporary storage |
| | | * @head: the head for your list. |
| | | * @member: the name of the list_struct within the struct. |
| | | * |
| | | * Iterate over list of given type, continuing after current point, |
| | | * safe against removal of list entry. |
| | | */ |
| | | #define list_for_each_entry_safe_continue(pos, n, head, member) \ |
| | | for (pos = list_entry(pos->member.next, typeof(*pos), member), \ |
| | | n = list_entry(pos->member.next, typeof(*pos), member); \ |
| | | &pos->member != (head); \ |
| | | pos = n, n = list_entry(n->member.next, typeof(*n), member)) |
| | | |
| | | /** |
| | | * list_for_each_entry_safe_from |
| | | * @pos: the type * to use as a loop cursor. |
| | | * @n: another type * to use as temporary storage |
| | | * @head: the head for your list. |
| | | * @member: the name of the list_struct within the struct. |
| | | * |
| | | * Iterate over list of given type from current point, safe against |
| | | * removal of list entry. |
| | | */ |
| | | #define list_for_each_entry_safe_from(pos, n, head, member) \ |
| | | for (n = list_entry(pos->member.next, typeof(*pos), member); \ |
| | | &pos->member != (head); \ |
| | | pos = n, n = list_entry(n->member.next, typeof(*n), member)) |
| | | |
| | | /** |
| | | * list_for_each_entry_safe_reverse |
| | | * @pos: the type * to use as a loop cursor. |
| | | * @n: another type * to use as temporary storage |
| | | * @head: the head for your list. |
| | | * @member: the name of the list_struct within the struct. |
| | | * |
| | | * Iterate backwards over list of given type, safe against removal |
| | | * of list entry. |
| | | */ |
| | | #define list_for_each_entry_safe_reverse(pos, n, head, member) \ |
| | | for (pos = list_entry((head)->prev, typeof(*pos), member), \ |
| | | n = list_entry(pos->member.prev, typeof(*pos), member); \ |
| | | &pos->member != (head); \ |
| | | pos = n, n = list_entry(n->member.prev, typeof(*n), member)) |
| | | |
| | | /* |
| | | * Double linked lists with a single pointer list head. |
| | | * Mostly useful for hash tables where the two pointer list head is |
| | | * too wasteful. |
| | | * You lose the ability to access the tail in O(1). |
| | | */ |
| | | |
| | | struct hlist_head { |
| | | struct hlist_node *first; |
| | | }; |
| | | |
| | | struct hlist_node { |
| | | struct hlist_node *next, **pprev; |
| | | }; |
| | | |
| | | #define HLIST_HEAD_INIT { .first = NULL } |
| | | #define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } |
| | | #define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) |
| | | static inline void INIT_HLIST_NODE(struct hlist_node *h) |
| | | { |
| | | h->next = NULL; |
| | | h->pprev = NULL; |
| | | } |
| | | |
| | | static inline int hlist_unhashed(const struct hlist_node *h) |
| | | { |
| | | return !h->pprev; |
| | | } |
| | | |
| | | static inline int hlist_empty(const struct hlist_head *h) |
| | | { |
| | | return !h->first; |
| | | } |
| | | |
| | | static inline void __hlist_del(struct hlist_node *n) |
| | | { |
| | | struct hlist_node *next = n->next; |
| | | struct hlist_node **pprev = n->pprev; |
| | | *pprev = next; |
| | | if (next) |
| | | next->pprev = pprev; |
| | | } |
| | | |
| | | static inline void hlist_del(struct hlist_node *n) |
| | | { |
| | | __hlist_del(n); |
| | | n->next = LIST_POISON1; |
| | | n->pprev = LIST_POISON2; |
| | | } |
| | | |
| | | static inline void hlist_del_init(struct hlist_node *n) |
| | | { |
| | | if (!hlist_unhashed(n)) { |
| | | __hlist_del(n); |
| | | INIT_HLIST_NODE(n); |
| | | } |
| | | } |
| | | |
| | | static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) |
| | | { |
| | | struct hlist_node *first = h->first; |
| | | n->next = first; |
| | | if (first) |
| | | first->pprev = &n->next; |
| | | h->first = n; |
| | | n->pprev = &h->first; |
| | | } |
| | | |
| | | /* next must be != NULL */ |
| | | static inline void hlist_add_before(struct hlist_node *n, |
| | | struct hlist_node *next) |
| | | { |
| | | n->pprev = next->pprev; |
| | | n->next = next; |
| | | next->pprev = &n->next; |
| | | *(n->pprev) = n; |
| | | } |
| | | |
| | | static inline void hlist_add_after(struct hlist_node *n, |
| | | struct hlist_node *next) |
| | | { |
| | | next->next = n->next; |
| | | n->next = next; |
| | | next->pprev = &n->next; |
| | | |
| | | if(next->next) |
| | | next->next->pprev = &next->next; |
| | | } |
| | | |
| | | #define hlist_entry(ptr, type, member) container_of(ptr,type,member) |
| | | |
| | | #define hlist_for_each(pos, head) \ |
| | | for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \ |
| | | pos = pos->next) |
| | | |
| | | #define hlist_for_each_safe(pos, n, head) \ |
| | | for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ |
| | | pos = n) |
| | | |
| | | /** |
| | | * hlist_for_each_entry - iterate over list of given type |
| | | * @tpos: the type * to use as a loop cursor. |
| | | * @pos: the &struct hlist_node to use as a loop cursor. |
| | | * @head: the head for your list. |
| | | * @member: the name of the hlist_node within the struct. |
| | | */ |
| | | #define hlist_for_each_entry(tpos, pos, head, member) \ |
| | | for (pos = (head)->first; \ |
| | | pos && ({ prefetch(pos->next); 1;}) && \ |
| | | ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ |
| | | pos = pos->next) |
| | | |
| | | /** |
| | | * hlist_for_each_entry_continue - iterate over a hlist continuing after current point |
| | | * @tpos: the type * to use as a loop cursor. |
| | | * @pos: the &struct hlist_node to use as a loop cursor. |
| | | * @member: the name of the hlist_node within the struct. |
| | | */ |
| | | #define hlist_for_each_entry_continue(tpos, pos, member) \ |
| | | for (pos = (pos)->next; \ |
| | | pos && ({ prefetch(pos->next); 1;}) && \ |
| | | ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ |
| | | pos = pos->next) |
| | | |
| | | /** |
| | | * hlist_for_each_entry_from - iterate over a hlist continuing from current point |
| | | * @tpos: the type * to use as a loop cursor. |
| | | * @pos: the &struct hlist_node to use as a loop cursor. |
| | | * @member: the name of the hlist_node within the struct. |
| | | */ |
| | | #define hlist_for_each_entry_from(tpos, pos, member) \ |
| | | for (; pos && ({ prefetch(pos->next); 1;}) && \ |
| | | ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ |
| | | pos = pos->next) |
| | | |
| | | /** |
| | | * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry |
| | | * @tpos: the type * to use as a loop cursor. |
| | | * @pos: the &struct hlist_node to use as a loop cursor. |
| | | * @n: another &struct hlist_node to use as temporary storage |
| | | * @head: the head for your list. |
| | | * @member: the name of the hlist_node within the struct. |
| | | */ |
| | | #define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ |
| | | for (pos = (head)->first; \ |
| | | pos && ({ n = pos->next; 1; }) && \ |
| | | ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ |
| | | pos = n) |
| | | |
| | | |
| | | #endif |
| | | |
| | | |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue <guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_log.c |
| | | * Description: This file is the linux infrastructural logger system library |
| | | * |
| | | * Version: 1.0.0(08/08/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "08/08/2012 04:24:01 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include "cp_logger.h" |
| | | #include "cp_common.h" |
| | | |
| | | #define PRECISE_TIME_FACTOR 1000 |
| | | |
| | | static unsigned long log_rollback_size = LOG_ROLLBACK_NONE; |
| | | |
| | | static cp_logger *logger = NULL; |
| | | |
| | | char *log_str[LOG_LEVEL_MAX + 1] = { "", "F", "E", "W", "N", "D", "I", "T", "M" }; |
| | | |
| | | static char *cp_time_format = DEFAULT_TIME_FORMAT; |
| | | |
| | | void cp_log_set_time_format(char *time_format) |
| | | { |
| | | cp_time_format = time_format; |
| | | } |
| | | |
| | | static void cp_log_default_signal_handler(int sig) |
| | | { |
| | | if(!logger) |
| | | return ; |
| | | |
| | | if (sig == SIGHUP) |
| | | { |
| | | signal(SIGHUP, cp_log_default_signal_handler); |
| | | log_fatal("SIGHUP received - reopenning log file [%s]", logger->file); |
| | | cp_log_reopen(); |
| | | } |
| | | } |
| | | |
| | | static void log_banner(char *prefix) |
| | | { |
| | | if(!logger) |
| | | return ; |
| | | |
| | | fprintf(logger->fp, "%s log \"%s\" on level [%s] size [%lu], log system version %s\n", |
| | | prefix, logger->file, log_str[logger->level], log_rollback_size / 1024, LOG_VERSION_STR); |
| | | #ifdef LOG_FILE_LINE |
| | | fprintf(logger->fp, " [Date] [Time] [Level] [PID/TID] [File/Line] [Content]\n"); |
| | | #else |
| | | fprintf(logger->fp, " [Date] [Time] [Level] [PID/TID] [Content]\n"); |
| | | #endif |
| | | fprintf(logger->fp, "-------------------------------------------------------------\n"); |
| | | } |
| | | |
| | | static void check_and_rollback(void) |
| | | { |
| | | if(!logger) |
| | | return ; |
| | | |
| | | if (log_rollback_size != LOG_ROLLBACK_NONE) |
| | | { |
| | | long _curOffset = ftell(logger->fp); |
| | | |
| | | if ((_curOffset != -1) && (_curOffset >= log_rollback_size)) |
| | | { |
| | | char cmd[512]; |
| | | |
| | | snprintf(cmd, sizeof(cmd), "cp -f %s %s.roll", logger->file, logger->file); |
| | | system(cmd); |
| | | |
| | | if (-1 == fseek(logger->fp, 0L, SEEK_SET)) |
| | | fprintf(logger->fp, "log rollback fseek failed \n"); |
| | | |
| | | rewind(logger->fp); |
| | | |
| | | truncate(logger->file, 0); |
| | | log_banner("Already rollback"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | cp_logger *cp_log_init(cp_logger *log, char *filename, int level, int log_size) |
| | | { |
| | | if(NULL == log) |
| | | { |
| | | logger = t_malloc(sizeof(cp_logger)); |
| | | memset(logger, 0, sizeof(cp_logger)); |
| | | logger->flag |= CP_LOGGER_MALLOC; |
| | | } |
| | | else |
| | | { |
| | | logger = log; |
| | | memset(logger, 0, sizeof(cp_logger)); |
| | | logger->flag |= CP_LOGGER_ARGUMENT; |
| | | } |
| | | |
| | | if(NULL == logger) |
| | | { |
| | | return NULL; |
| | | } |
| | | |
| | | strncpy(logger->file, filename, FILENAME_LEN); |
| | | logger->level = level; |
| | | logger->size = log_size; |
| | | |
| | | return logger; |
| | | } |
| | | |
| | | int cp_log_open(void) |
| | | { |
| | | struct sigaction act; |
| | | char *filemode; |
| | | |
| | | if(!logger) |
| | | { |
| | | return -1; |
| | | } |
| | | |
| | | log_rollback_size = logger->size <= 0 ? LOG_ROLLBACK_NONE : logger->size*1024; /* Unit KiB */ |
| | | |
| | | if ('\0' == logger->file) |
| | | return -1; |
| | | |
| | | if (!strcmp(logger->file, DBG_LOG_FILE)) |
| | | { |
| | | logger->fp = stderr; |
| | | log_rollback_size = LOG_ROLLBACK_NONE; |
| | | logger->flag |= CP_LOGGER_CONSOLE; |
| | | goto OUT; |
| | | } |
| | | |
| | | //filemode = (log_rollback_size==LOG_ROLLBACK_NONE) ? "a+" : "w+"; |
| | | filemode = "a+"; |
| | | |
| | | logger->fp = fopen(logger->file, filemode); |
| | | if (NULL == logger->fp) |
| | | { |
| | | fprintf(stderr, "Open log file \"%s\" in %s failure\n", logger->file, filemode); |
| | | return -2; |
| | | } |
| | | |
| | | act.sa_handler = cp_log_default_signal_handler; |
| | | sigemptyset(&act.sa_mask); |
| | | act.sa_flags = 0; |
| | | sigaction(SIGHUP, &act, NULL); |
| | | |
| | | OUT: |
| | | log_banner("Initialize"); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | void cp_log_close(void) |
| | | { |
| | | if (!logger || !logger->fp ) |
| | | return; |
| | | |
| | | log_banner("\nTerminate"); |
| | | cp_log_raw("\n\n\n\n"); |
| | | |
| | | fflush(logger->fp); |
| | | |
| | | fclose(logger->fp); |
| | | logger->fp = NULL; |
| | | |
| | | return ; |
| | | } |
| | | |
| | | int cp_log_reopen(void) |
| | | { |
| | | int rc = 0; |
| | | char *filemode; |
| | | |
| | | if( !logger ) |
| | | return -1; |
| | | |
| | | if (logger->flag & CP_LOGGER_CONSOLE ) |
| | | { |
| | | fflush(logger->fp); |
| | | logger->fp = stderr; |
| | | return 0; |
| | | } |
| | | |
| | | if (logger->fp) |
| | | { |
| | | cp_log_close(); |
| | | //filemode = log_rollback_size == LOG_ROLLBACK_NONE ? "a+" : "w+"; |
| | | filemode = "a+"; |
| | | logger->fp = fopen(logger->file, filemode); |
| | | |
| | | if (logger->fp == NULL) |
| | | rc = -2; |
| | | } |
| | | else |
| | | { |
| | | rc = -3; |
| | | } |
| | | |
| | | if (!rc) |
| | | { |
| | | log_banner("\nReopen"); |
| | | } |
| | | return rc; |
| | | } |
| | | |
| | | void cp_log_term(void) |
| | | { |
| | | if(!logger) |
| | | return ; |
| | | |
| | | cp_log_close(); |
| | | |
| | | if (logger->flag & CP_LOGGER_MALLOC ) |
| | | { |
| | | t_free(logger); |
| | | } |
| | | logger = NULL; |
| | | } |
| | | |
| | | void cp_log_raw(const char *fmt, ...) |
| | | { |
| | | va_list argp; |
| | | |
| | | if (!logger || !logger->fp) |
| | | return; |
| | | |
| | | check_and_rollback(); |
| | | |
| | | va_start(argp, fmt); |
| | | vfprintf(logger->fp, fmt, argp); |
| | | va_end(argp); |
| | | } |
| | | |
| | | static void cp_printout(char *level, char *fmt, va_list argp) |
| | | { |
| | | char buf[MAX_LOG_MESSAGE_LEN]; |
| | | struct tm *local; |
| | | struct timeval now; |
| | | char timestr[256]; |
| | | |
| | | if(!logger) |
| | | return ; |
| | | |
| | | pthread_t tid; |
| | | |
| | | check_and_rollback(); |
| | | |
| | | #ifdef MULTHREADS |
| | | tid = pthread_self(); |
| | | #else |
| | | tid = getpid(); |
| | | #endif |
| | | |
| | | gettimeofday(&now, NULL); |
| | | local = localtime(&now.tv_sec); |
| | | |
| | | strftime(timestr, 256, cp_time_format, local); |
| | | vsnprintf(buf, MAX_LOG_MESSAGE_LEN, fmt, argp); |
| | | |
| | | #ifdef DUMPLICATE_OUTPUT |
| | | printf("%s.%03ld [%s] [%06lu]: %s", |
| | | timestr, now.tv_usec / PRECISE_TIME_FACTOR, level, tid, buf); |
| | | #endif |
| | | |
| | | if (logger->fp) |
| | | fprintf(logger->fp, "%s.%03ld [%s] [%06lu]: %s", timestr, now.tv_usec / PRECISE_TIME_FACTOR, |
| | | level, tid, buf); |
| | | |
| | | if (logger->fp) |
| | | fflush(logger->fp); |
| | | } |
| | | |
| | | static void cp_printout_line(char *level, char *fmt, char *file, int line, va_list argp) |
| | | { |
| | | char buf[MAX_LOG_MESSAGE_LEN]; |
| | | struct tm *local; |
| | | struct timeval now; |
| | | char timestr[256]; |
| | | |
| | | if(!logger) |
| | | return ; |
| | | |
| | | pthread_t tid; |
| | | |
| | | check_and_rollback(); |
| | | |
| | | #ifdef MULTHREADS |
| | | tid = pthread_self(); |
| | | #else |
| | | tid = getpid(); |
| | | #endif |
| | | |
| | | gettimeofday(&now, NULL); |
| | | local = localtime(&now.tv_sec); |
| | | |
| | | strftime(timestr, 256, cp_time_format, local); |
| | | vsnprintf(buf, MAX_LOG_MESSAGE_LEN, fmt, argp); |
| | | |
| | | #ifdef DUMPLICATE_OUTPUT |
| | | printf("%s.%03ld [%s] [%06lu] (%s [%04d]) : %s", |
| | | timestr, now.tv_usec / PRECISE_TIME_FACTOR, level, tid, file, line, buf); |
| | | #endif |
| | | |
| | | if (logger->fp) |
| | | fprintf(logger->fp, "%s.%03ld [%s] [%06lu] (%s [%04d]) : %s", |
| | | timestr, now.tv_usec / PRECISE_TIME_FACTOR, level, tid, file, line, buf); |
| | | |
| | | if (logger->fp) |
| | | fflush(logger->fp); |
| | | } |
| | | |
| | | void cp_log(int level, char *fmt, ...) |
| | | { |
| | | va_list argp; |
| | | |
| | | if (!logger || level>logger->level) |
| | | return; |
| | | |
| | | va_start(argp, fmt); |
| | | cp_printout(log_str[level], fmt, argp); |
| | | va_end(argp); |
| | | } |
| | | |
| | | void cp_log_line(int level, char *file, int line, char *fmt, ...) |
| | | { |
| | | va_list argp; |
| | | |
| | | if (!logger || level>logger->level) |
| | | return; |
| | | |
| | | va_start(argp, fmt); |
| | | cp_printout_line(log_str[level], fmt, file, line, argp); |
| | | |
| | | va_end(argp); |
| | | } |
| | | |
| | | #define LINELEN 81 |
| | | #define CHARS_PER_LINE 16 |
| | | static char *print_char = |
| | | " " |
| | | " " |
| | | " !\"#$%&'()*+,-./" |
| | | "0123456789:;<=>?" |
| | | "@ABCDEFGHIJKLMNO" |
| | | "PQRSTUVWXYZ[\\]^_" |
| | | "`abcdefghijklmno" |
| | | "pqrstuvwxyz{|}~ " |
| | | " " |
| | | " " |
| | | " ???????????????" |
| | | "????????????????" |
| | | "????????????????" |
| | | "????????????????" |
| | | "????????????????" |
| | | "????????????????"; |
| | | |
| | | void cp_log_dump(int level, char *buf, int len) |
| | | { |
| | | int rc; |
| | | int idx; |
| | | char prn[LINELEN]; |
| | | char lit[CHARS_PER_LINE + 2]; |
| | | char hc[4]; |
| | | short line_done = 1; |
| | | |
| | | if (!logger || level>logger->level) |
| | | return; |
| | | |
| | | rc = len; |
| | | idx = 0; |
| | | lit[CHARS_PER_LINE] = '\0'; |
| | | |
| | | while (rc > 0) |
| | | { |
| | | if (line_done) |
| | | snprintf(prn, LINELEN, "%08X: ", idx); |
| | | |
| | | do |
| | | { |
| | | unsigned char c = buf[idx]; |
| | | snprintf(hc, 4, "%02X ", c); |
| | | strncat(prn, hc, LINELEN); |
| | | |
| | | lit[idx % CHARS_PER_LINE] = print_char[c]; |
| | | } |
| | | while (--rc > 0 && (++idx % CHARS_PER_LINE != 0)); |
| | | |
| | | line_done = (idx % CHARS_PER_LINE) == 0; |
| | | if (line_done) |
| | | { |
| | | #ifdef DUMPLICATE_OUTPUT |
| | | printf("%s %s\n", prn, lit); |
| | | #endif |
| | | if (logger->fp) |
| | | fprintf(logger->fp, "%s %s\n", prn, lit); |
| | | } |
| | | } |
| | | |
| | | if (!line_done) |
| | | { |
| | | int ldx = idx % CHARS_PER_LINE; |
| | | lit[ldx++] = print_char[(int)buf[idx]]; |
| | | lit[ldx] = '\0'; |
| | | |
| | | while ((++idx % CHARS_PER_LINE) != 0) |
| | | strncat(prn, " ", LINELEN); |
| | | |
| | | #ifdef DUMPLICATE_OUTPUT |
| | | printf("%s %s\n", prn, lit); |
| | | #endif |
| | | if (logger->fp) |
| | | fprintf(logger->fp, "%s %s\n", prn, lit); |
| | | |
| | | } |
| | | } |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2012 Guo Wenxue <guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_logger.h |
| | | * Description: This file is the linux infrastructural logger system library |
| | | * |
| | | * Version: 1.0.0(08/08/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "08/08/2012 05:16:56 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #ifndef __CP_LOG_H |
| | | #define __CP_LOG_H |
| | | |
| | | #include <stdarg.h> |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <string.h> |
| | | #include <unistd.h> |
| | | #include <signal.h> |
| | | #include <time.h> |
| | | #include <errno.h> |
| | | |
| | | #include <pthread.h> |
| | | #include <sys/types.h> |
| | | #include <sys/time.h> |
| | | |
| | | #define LOG_VERSION_STR "1.0.0" |
| | | |
| | | #ifndef FILENAME_LEN |
| | | #define FILENAME_LEN 64 |
| | | #endif |
| | | |
| | | #define DEFAULT_LOGFILE "cp_logger.log" |
| | | #define DBG_LOG_FILE "console" /* Debug mode log file is console */ |
| | | |
| | | #define LOG_ROLLBACK_SIZE 512 /* Default rollback log size */ |
| | | #define LOG_ROLLBACK_NONE 0 /* Set rollback size to 0 will not rollback */ |
| | | |
| | | #define DEFAULT_TIME_FORMAT "%Y-%m-%d %H:%M:%S" |
| | | #define MAX_LOG_MESSAGE_LEN 0x1000 |
| | | |
| | | //#define DUMPLICATE_OUTPUT /* Log to file and printf on console */ |
| | | #define LOG_FILE_LINE /* Log the file and line */ |
| | | |
| | | enum |
| | | { |
| | | LOG_LEVEL_DISB = 0, /* Disable "Debug" */ |
| | | LOG_LEVEL_FATAL, /* Debug Level "Fatal" */ |
| | | LOG_LEVEL_ERROR, /* Debug Level "ERROR" */ |
| | | LOG_LEVEL_WARN, /* Debug Level "warnning" */ |
| | | LOG_LEVEL_NRML, /* Debug Level "Normal" */ |
| | | LOG_LEVEL_DEBUG, /* Debug Level "Debug" */ |
| | | LOG_LEVEL_INFO, /* Debug Level "Information" */ |
| | | LOG_LEVEL_TRACE, /* Debug Level "Trace" */ |
| | | LOG_LEVEL_MAX, |
| | | }; |
| | | |
| | | #define CP_LOGGER_MALLOC 1<<0 |
| | | #define CP_LOGGER_ARGUMENT 0<<0 |
| | | |
| | | #define CP_LOGGER_CONSOLE 1<<1 |
| | | #define CP_LOGGER_FILE 0<<1 |
| | | |
| | | #define CP_LOGGER_LEVEL_OPT 1<<2 /* The log level is sepcified by the command option */ |
| | | typedef struct _cp_logger |
| | | { |
| | | unsigned char flag; /* This logger pointer is malloc() or passed by argument */ |
| | | char file[FILENAME_LEN]; |
| | | int level; |
| | | int size; |
| | | |
| | | FILE *fp; |
| | | } cp_logger; |
| | | |
| | | extern char *log_str[]; |
| | | |
| | | extern cp_logger *cp_log_init(cp_logger *log, char *filename, int level, int log_size); |
| | | extern int cp_log_open(void); |
| | | extern void cp_log_set_time_format(char *time_format); |
| | | extern int cp_log_reopen(void); |
| | | extern void cp_log_term(void); |
| | | extern void cp_log_raw(const char *fmt, ...); |
| | | extern void cp_log(int level, char *fmt, ...); |
| | | extern void cp_log_line(int level, char *file, int line, char *fmt, ...); |
| | | |
| | | extern void cp_log_dump(int level, char *buf, int len); |
| | | |
| | | #ifdef LOG_FILE_LINE |
| | | #define log_trace(fmt, ...) cp_log_line(LOG_LEVEL_TRACE, __FILE__, __LINE__, fmt, ##__VA_ARGS__) |
| | | #define log_info(fmt, ...) cp_log_line(LOG_LEVEL_INFO, __FILE__, __LINE__, fmt, ##__VA_ARGS__) |
| | | #define log_dbg(fmt, ...) cp_log_line(LOG_LEVEL_DEBUG, __FILE__, __LINE__, fmt, ##__VA_ARGS__) |
| | | #define log_nrml(fmt, ...) cp_log_line(LOG_LEVEL_NRML, __FILE__, __LINE__, fmt, ##__VA_ARGS__) |
| | | #define log_warn(fmt, ...) cp_log_line(LOG_LEVEL_WARN, __FILE__, __LINE__, fmt, ##__VA_ARGS__) |
| | | #define log_err(fmt, ...) cp_log_line(LOG_LEVEL_ERROR, __FILE__, __LINE__, fmt, ##__VA_ARGS__) |
| | | #define log_fatal(fmt, ...) cp_log_line(LOG_LEVEL_FATAL, __FILE__, __LINE__, fmt, ##__VA_ARGS__) |
| | | #else |
| | | #define log_trace(fmt, ...) cp_log(LOG_LEVEL_TRACE, fmt, ##__VA_ARGS__) |
| | | #define log_info(fmt, ...) cp_log(LOG_LEVEL_INFO, fmt, ##__VA_ARGS__) |
| | | #define log_dbg(fmt, ...) cp_log(LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__) |
| | | #define log_nrml(fmt, ...) cp_log(LOG_LEVEL_NRML, fmt, ##__VA_ARGS__) |
| | | #define log_warn(fmt, ...) cp_log(LOG_LEVEL_WARN, fmt, ##__VA_ARGS__) |
| | | #define log_err(fmt, ...) cp_log(LOG_LEVEL_ERROR, fmt, ##__VA_ARGS__) |
| | | #define log_fatal(fmt, ...) cp_log(LOG_LEVEL_FATAL, fmt, ##__VA_ARGS__) |
| | | #endif |
| | | |
| | | |
| | | #endif /* __CP_LOG_H */ |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_network.c |
| | | * Description: This file is the high level network library API |
| | | * |
| | | * Version: 1.0.0(10/31/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "10/31/2012 11:22:38 AM" |
| | | * |
| | | ********************************************************************************/ |
| | | #include <netinet/in.h> |
| | | #include <net/if.h> |
| | | #include <net/if_arp.h> |
| | | #include <arpa/inet.h> |
| | | |
| | | #include "cp_sock.h" |
| | | #include "cp_fds.h" |
| | | #include "cp_network.h" |
| | | #include "cp_network.h" |
| | | #include "cp_proc.h" |
| | | |
| | | /* Description: Configure the NIC MAC/IP address |
| | | * Input args: $nic: configure for which NIC(Network Interface Card): eth0, eth1 |
| | | * $mac: MAC address $ip: IP address |
| | | * Return Value: 0: Test OK, <0: Failed |
| | | */ |
| | | int nic_network_config(char *nic, char *mac, char *ip) |
| | | { |
| | | if(!nic) |
| | | return -1; |
| | | |
| | | /*MAC address format: aa:bb:cc:dd:ee:ff */ |
| | | if(mac && 17==strlen(mac)) |
| | | { |
| | | /* shutdown the ethernet and clear the original IP address */ |
| | | exec_system_cmd("ifconfig %s down", nic, nic); |
| | | sleep(1); |
| | | exec_system_cmd("ifconfig %s hw ether %s up", nic, mac); |
| | | } |
| | | |
| | | /* IP address specified and valid */ |
| | | if(ip && inet_addr(ip)) |
| | | { |
| | | exec_system_cmd("ifconfig %s down && ifconfig %s 0.0.0.0", nic, nic); |
| | | sleep(2); |
| | | exec_system_cmd("ifconfig %s %s up", nic, ip); |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | int nic_get_ipaddr(char *nic, char *ipaddr) |
| | | { |
| | | int fd; |
| | | struct ifreq ifr; |
| | | struct sockaddr_in *sin; |
| | | |
| | | if( !nic || !ipaddr ) |
| | | return -1; |
| | | |
| | | fd = socket(AF_INET, SOCK_DGRAM, 0); |
| | | strcpy(ifr.ifr_name, nic); |
| | | |
| | | if ((ioctl(fd, SIOCGIFADDR, (caddr_t)&ifr, sizeof(struct ifreq))) < 0) |
| | | { |
| | | log_fatal("System call ioctl() with SIOCGIFADDR get %s IP address failure.\n", nic); |
| | | return -2; |
| | | } |
| | | |
| | | sin = (struct sockaddr_in *)&ifr.ifr_addr; |
| | | strcpy(ipaddr, (const char *)inet_ntoa(sin->sin_addr)); |
| | | |
| | | log_dbg("Get %s local IP address: %s\n", nic, ipaddr); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int nic_get_ptpaddr(char *nic, char *ptpaddr) |
| | | { |
| | | int fd; |
| | | struct ifreq ifr; |
| | | struct sockaddr_in *sin; |
| | | |
| | | fd = socket(AF_INET, SOCK_DGRAM, 0); |
| | | strcpy(ifr.ifr_name, nic); |
| | | |
| | | if ((ioctl(fd, SIOCGIFDSTADDR, (caddr_t) & ifr, sizeof(struct ifreq))) < 0) |
| | | { |
| | | log_fatal("System call ioctl() with SIOCGIFDSTADDR get %s IP address failure.\n", nic); |
| | | return -1; |
| | | } |
| | | |
| | | sin = (struct sockaddr_in *)&ifr.ifr_dstaddr; |
| | | strcpy(ptpaddr, (const char *)inet_ntoa(sin->sin_addr)); |
| | | log_dbg("Get %s remote IP address: %s\n", nic, ptpaddr); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | /* Description: Use ping do network test |
| | | * Input args: $from: : use which NIC(Network Interface Card: eth0, eth1) or |
| | | * source IP address do ping test. if it's NULL, use default route |
| | | * $ping_ip: The ping test destination IP address |
| | | * Output args: NONE |
| | | * Return Value: >=0 ping test packet lost percent, <0: failure |
| | | */ |
| | | int network_ping_test(char *from, char *ping_ip) |
| | | { |
| | | FILE *fp; |
| | | char cmd[256]; |
| | | char buf[512]; |
| | | int lost_percent = 100; |
| | | unsigned long tx_packets = 0; |
| | | unsigned long rx_packets = 0; |
| | | |
| | | memset(cmd, 0, sizeof(cmd)); |
| | | if(from) |
| | | { |
| | | snprintf(cmd, sizeof(cmd), "ping -W1 -c5 -s4 %s -I %s", ping_ip, from); |
| | | } |
| | | else |
| | | { |
| | | snprintf(cmd, sizeof(cmd), "ping -W1 -c5 -s4 %s", ping_ip); |
| | | } |
| | | |
| | | if (NULL == (fp = popen(cmd, "r"))) |
| | | { |
| | | return -2; |
| | | } |
| | | |
| | | while (NULL != fgets(buf, sizeof(buf), fp)) |
| | | { |
| | | if (strstr(buf, "transmitted")) |
| | | { |
| | | split_string_to_value(buf, "%l,%l,%d", &tx_packets, &rx_packets, &lost_percent); |
| | | break; |
| | | } |
| | | } |
| | | |
| | | pclose(fp); |
| | | return lost_percent; |
| | | } |
| | | |
| | | |
| | | int cp_sock_accept_regist(CP_SOCK *serv_sock) |
| | | { |
| | | CP_SOCK *new_sock = NULL; |
| | | int rv = 0; |
| | | |
| | | if(!serv_sock) |
| | | { |
| | | log_err("Invalude input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | log_dbg("Accept and regist new client from server [%d] on [%s:%d] now\n", |
| | | serv_sock->fd, serv_sock->laddr, serv_sock->lport); |
| | | |
| | | if(serv_sock->accept_cnt >= serv_sock->max_client) |
| | | { |
| | | log_err("No more client resource aviable on server socket [%d]\n", serv_sock->fd); |
| | | goto exit_out; |
| | | } |
| | | |
| | | if( !(new_sock=cp_sock_init(NULL, CP_SOCK_RCVBUF, CP_SOCK_SNDBUF, CP_SOCK_KEEPINTVL, CP_SOCK_KEEPCNT)) ) |
| | | { |
| | | log_err("Create a new socket contex for accept new client failed.\n"); |
| | | goto exit_out; |
| | | } |
| | | |
| | | new_sock->serv_sock = serv_sock; |
| | | new_sock->fds = serv_sock->fds; |
| | | new_sock->privt = serv_sock->privt; |
| | | new_sock->cbfunc = serv_sock->client_func; |
| | | new_sock->mode = CP_SOCK_MODE_ACCEPT; |
| | | |
| | | /* add accept new client into the socket registry list */ |
| | | if( cp_fds_add_sock_registry(new_sock) ) |
| | | { |
| | | rv = -2; |
| | | goto term_sock; |
| | | } |
| | | |
| | | /* accept the new client from server socket */ |
| | | if( cp_sock_accept(serv_sock, new_sock) ) |
| | | { |
| | | rv = -3; |
| | | goto del_regist; |
| | | } |
| | | |
| | | if( cp_add_epoll_event(new_sock) ) |
| | | { |
| | | rv = -4; |
| | | goto del_regist; |
| | | } |
| | | |
| | | log_dbg("Accept and regist new client from server [%d] on [%s:%d] ok\n", |
| | | serv_sock->fd, serv_sock->laddr, serv_sock->lport); |
| | | |
| | | return 0; |
| | | |
| | | del_regist: |
| | | cp_fds_del_sock_registry(new_sock); |
| | | |
| | | term_sock: |
| | | if(new_sock) |
| | | cp_sock_term_clear(new_sock); |
| | | |
| | | exit_out: |
| | | log_err("Accept and regist new client from server [%d] on [%s:%d] failed\n", |
| | | serv_sock->fd, serv_sock->laddr, serv_sock->lport); |
| | | |
| | | cp_fds_del_sock_task(serv_sock); |
| | | return rv; |
| | | } |
| | | |
| | | CP_SOCK *cp_sock_connect_regist(CP_FDS *fds, CP_SOCK *sock, char *raddr, int rport, int lport, CP_SOCK_EVENT_CALLBACK service_route) |
| | | { |
| | | if(!fds || !raddr || rport<0) |
| | | { |
| | | log_err("Invalude input arguments\n"); |
| | | goto exit_out; |
| | | } |
| | | |
| | | if( !sock && !(sock=cp_sock_init(sock, CP_SOCK_RCVBUF, CP_SOCK_SNDBUF, CP_SOCK_KEEPINTVL, CP_SOCK_KEEPCNT)) ) |
| | | { |
| | | goto exit_out; |
| | | } |
| | | |
| | | if( SOCK_STAT_CONNECTED == sock->status ) |
| | | return sock; /* already ok now */ |
| | | |
| | | if( !(sock->flag&FLAG_SOCK_REGISTRY) ) |
| | | { |
| | | sock->fds = fds; |
| | | sock->cbfunc = service_route; |
| | | sock->mode = CP_SOCK_MODE_CONNECT; |
| | | strncpy(sock->laddr, "0.0.0.0", sizeof(sock->laddr)); |
| | | log_dbg("Connect and regist socket to remote [%s:%d] now\n", raddr, rport); |
| | | |
| | | if( cp_fds_add_sock_registry( sock) ) |
| | | goto term_sock; /* regist to the list failed */ |
| | | } |
| | | |
| | | if ( cp_sock_connect(sock, raddr, rport, lport) ) |
| | | { |
| | | log_dbg("socket [%d] connect failed, start to remove registry it now.\n", sock->fd); |
| | | goto del_regist; |
| | | } |
| | | else |
| | | { |
| | | if( cp_add_epoll_event(sock) ) |
| | | goto del_regist; |
| | | } |
| | | |
| | | return sock; |
| | | |
| | | del_regist: |
| | | cp_fds_del_sock_registry(sock); |
| | | |
| | | term_sock: |
| | | cp_fds_del_sock_task(sock); |
| | | if(sock) |
| | | cp_sock_term(sock); |
| | | |
| | | exit_out: |
| | | log_err("Connect and regist new socket to remote server [%s:%d] failed\n", raddr, rport); |
| | | return NULL; |
| | | } |
| | | |
| | | CP_SOCK *cp_sock_server_regist(CP_FDS *fds, char *addr, int port, int max_client, CP_SOCK_EVENT_CALLBACK service_route, void *data) |
| | | { |
| | | int rv = 0; |
| | | |
| | | CP_SOCK *sock = NULL; |
| | | |
| | | log_dbg("Regist socket server listen on [%s:%d] now\n", addr?addr:"local", port); |
| | | |
| | | if(!fds || port < 0) |
| | | { |
| | | rv = -1; |
| | | log_err("Invalude input arguments\n"); |
| | | goto exit_out; |
| | | } |
| | | |
| | | if( !(sock=cp_sock_init(NULL, CP_SOCK_RCVBUF, CP_SOCK_SNDBUF, CP_SOCK_KEEPINTVL, CP_SOCK_KEEPCNT)) ) |
| | | { |
| | | rv = -2; |
| | | goto exit_out; |
| | | } |
| | | |
| | | INIT_LIST_HEAD(&sock->accept_list); |
| | | sock->fds = fds; |
| | | sock->cbfunc = cp_sock_accept_regist; |
| | | sock->client_func = service_route; |
| | | sock->privt = data; |
| | | sock->mode = CP_SOCK_MODE_LISTEN; |
| | | |
| | | if( cp_fds_add_sock_registry(sock) ) |
| | | { |
| | | rv = -3; |
| | | goto term_sock; |
| | | } |
| | | |
| | | /* If specified maximum clients <=0, then use the default one */ |
| | | sock->max_client = max_client<=0 ? CP_DEF_MAX_CLIENTS : max_client; |
| | | |
| | | /* If specified maximum clients larger than FDS monitor maxevents, then use the default one */ |
| | | sock->max_client = max_client<fds->max_event ? sock->max_client : CP_DEF_MAX_CLIENTS; |
| | | |
| | | if( cp_sock_listen(sock, addr, port, sock->max_client) ) |
| | | { |
| | | rv = -4; |
| | | goto del_regist; |
| | | } |
| | | |
| | | /* Add server socket FD to the epoll monitor list */ |
| | | if( cp_add_epoll_event(sock) ) |
| | | { |
| | | rv = -5; |
| | | goto del_regist; |
| | | } |
| | | |
| | | log_nrml("Registe socket[%d] server listen on [%s:%d] ok.\n", sock->fd, sock->laddr, sock->lport); |
| | | return sock; |
| | | |
| | | del_regist: |
| | | cp_fds_del_sock_registry(sock); |
| | | |
| | | term_sock: |
| | | cp_fds_del_sock_task(sock); |
| | | if(sock) |
| | | cp_sock_term_clear(sock); |
| | | |
| | | exit_out: |
| | | log_err("Registe socket server listen on [%s:%d] failed.\n", addr, port); |
| | | return NULL; |
| | | } |
| | | |
| | | void cp_sock_term_all_service(CP_FDS *fds) |
| | | { |
| | | if(!fds) |
| | | return; |
| | | |
| | | log_dbg("Terminate all the service now\n"); |
| | | |
| | | cp_sock_term_all_task(fds); |
| | | cp_sock_term_all_server(fds); |
| | | cp_sock_term_all_client(fds); |
| | | |
| | | cp_fds_term(fds); |
| | | log_warn("Terminate all the service ok\n"); |
| | | } |
| | | |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_network.h |
| | | * Description: This head file |
| | | * |
| | | * Version: 1.0.0(10/31/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "10/31/2012 11:24:06 AM" |
| | | * |
| | | ********************************************************************************/ |
| | | #ifndef __CP_NETWORK_H |
| | | #define __CP_NETWORK_H |
| | | |
| | | #include "cp_fds.h" |
| | | #include "cp_sock.h" |
| | | |
| | | #define CP_DEF_MAX_CLIENTS 1024 |
| | | #define CP_DEF_TIMEOUT 10 |
| | | |
| | | extern int nic_network_config(char *nic, char *mac, char *ip); |
| | | extern int nic_get_ipaddr(char *nic, char *ipaddr); |
| | | extern int nic_get_ptpaddr(char *nic, char *ptpaddr); |
| | | extern int network_ping_test(char *from, char *ping_ip); |
| | | |
| | | extern int cp_sock_accept_regist(CP_SOCK *serv_sock); |
| | | |
| | | extern CP_SOCK *cp_sock_connect_regist(CP_FDS *fds, CP_SOCK *sock, char *raddr, int rport, int lport, CP_SOCK_EVENT_CALLBACK service_route); |
| | | |
| | | extern CP_SOCK *cp_sock_server_regist(CP_FDS *fds, char *addr, int port, int max_client, CP_SOCK_EVENT_CALLBACK service_route, void *data); |
| | | |
| | | extern void cp_sock_term_all_service(CP_FDS *fds); |
| | | #define cp_sock_term_all_service_clear(fds) {cp_sock_term_all_service(fds); fds=NULL;} |
| | | |
| | | #endif |
| | | |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) guowenxue <guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: ppp.c |
| | | * Description: This file is the ppp thread file,used to do PPP dial up |
| | | * |
| | | * Version: 1.0.0(02/02/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "02/02/2012 11:33:33 AM" |
| | | * |
| | | ********************************************************************************/ |
| | | #include <sys/ioctl.h> |
| | | #include <netinet/in.h> |
| | | #include <net/if.h> |
| | | #include <net/if_arp.h> |
| | | #include <arpa/inet.h> |
| | | #include "cp_ppp.h" |
| | | #include "cp_string.h" |
| | | #include "cp_iniparser.h" |
| | | #include "cp_network.h" |
| | | //#include "gsmd.h" |
| | | |
| | | /* |
| | | * Description: Check PPP10 device exist or not, and set the PPP context status |
| | | * |
| | | * |
| | | * Return Value: 0: PPP10 device exist -1:PPP10 device not exist |
| | | * |
| | | */ |
| | | int check_ppp_interface(char *ppp_dev) |
| | | { |
| | | int fd = -1; |
| | | int retval = -1; |
| | | char buf[512]; |
| | | |
| | | if ((fd = open("/proc/net/dev", O_RDONLY, 0666)) < 0) |
| | | { |
| | | return -1; /* System error, take as PPP10 device not exist too */ |
| | | } |
| | | |
| | | while (read(fd, buf, sizeof(buf)) > 0) |
| | | { |
| | | if (NULL != strstr(buf, ppp_dev)) |
| | | { |
| | | retval = 0; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | close(fd); |
| | | return retval; |
| | | } |
| | | |
| | | int check_ppp_ipaddr(PPPD_INFO *pppd_info, char *ppp_dev) |
| | | { |
| | | int fd; |
| | | struct ifreq ifr; |
| | | struct sockaddr_in *sin; |
| | | |
| | | if(check_ppp_interface(ppp_dev)) |
| | | return -2; |
| | | |
| | | fd = socket(AF_INET, SOCK_DGRAM, 0); |
| | | strcpy(ifr.ifr_name, ppp_dev); |
| | | |
| | | if ((ioctl(fd, SIOCGIFADDR, (caddr_t) & ifr, sizeof(struct ifreq))) < 0) |
| | | { |
| | | log_fatal("System call ioctl() with SIOCGIFADDR failure.\n", ppp_dev); |
| | | return -1; |
| | | } |
| | | |
| | | sin = (struct sockaddr_in *)&ifr.ifr_addr; |
| | | strcpy(pppd_info->netaddr, (const char *)inet_ntoa(sin->sin_addr)); |
| | | log_nrml("Get %s local IP address: %s\n", ppp_dev, pppd_info->netaddr); |
| | | |
| | | if ((ioctl(fd, SIOCGIFDSTADDR, (caddr_t) & ifr, sizeof(struct ifreq))) < 0) |
| | | { |
| | | log_fatal("System call ioctl() with SIOCGIFDSTADDR failure.\n", ppp_dev); |
| | | return -1; |
| | | } |
| | | sin = (struct sockaddr_in *)&ifr.ifr_dstaddr; |
| | | strcpy(pppd_info->ptpaddr, (const char *)inet_ntoa(sin->sin_addr)); |
| | | log_nrml("Get %s remote IP address: %s\n", ppp_dev, pppd_info->ptpaddr); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int check_ppp_stat(PPP_STAT *ppp_stat, char *ppp_dev) |
| | | { |
| | | int retval; |
| | | FILE *fp; |
| | | char *ptr; |
| | | char buf[512]; |
| | | |
| | | if( NULL == (fp=fopen(PPP_PROC_NET_DEV, "r")) ) |
| | | { |
| | | log_err("Can not open %s.\n", PPP_PROC_NET_DEV); |
| | | return -1; |
| | | } |
| | | |
| | | fgets(buf, sizeof(buf), fp); |
| | | fgets(buf, sizeof(buf), fp); |
| | | |
| | | while (fgets(buf, sizeof(buf), fp)) |
| | | { |
| | | ptr=strstr(buf, ppp_dev); |
| | | if(NULL == ptr) |
| | | { |
| | | log_err("Can not find %s interface statistic data in %s\n", ppp_dev, PPP_PROC_NET_DEV); |
| | | retval = -1; |
| | | break; |
| | | } |
| | | else |
| | | { |
| | | ptr = strchr(ptr, ':'); |
| | | ptr++; |
| | | sscanf(ptr, "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu", |
| | | &(ppp_stat->ullRx_Bytes), |
| | | &(ppp_stat->ullRx_Packets), |
| | | &(ppp_stat->ulRx_Errors), |
| | | &(ppp_stat->ulRx_Dropped), |
| | | &(ppp_stat->ulRx_FIFO_Errors), |
| | | &(ppp_stat->ulRx_Frame_Errors), |
| | | &(ppp_stat->ulRx_Compressed), |
| | | &(ppp_stat->ulRx_Multicast), |
| | | &(ppp_stat->ullTx_Bytes), |
| | | &(ppp_stat->ullTx_Packets), |
| | | &(ppp_stat->ulTx_Errors), |
| | | &(ppp_stat->ulTx_Dropped), |
| | | &(ppp_stat->ulTx_FIFO_Errors), |
| | | &(ppp_stat->ulCollisions), |
| | | &(ppp_stat->ulTx_Carrier_Errors), |
| | | &(ppp_stat->ulTx_Compressed) |
| | | ); |
| | | retval = 0; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if(0 == retval ) |
| | | log_dbg("Check PPP network traffic: Tx %llu bytes, Rx %llu bytes.\n", ppp_stat->ullTx_Bytes, ppp_stat->ullRx_Bytes); |
| | | fclose(fp); |
| | | return retval; |
| | | } |
| | | |
| | | int kill_pppd_process(COM_PORT *comport) |
| | | { |
| | | int pid = -1; |
| | | |
| | | while( (pid=check_pppd_pid(comport->dev_name)) > 0) |
| | | { |
| | | log_nrml("Terminate pppd process [pid=%d]\n", pid); |
| | | kill(pid, SIGTERM); |
| | | sleep(1); /* Wait pppd process exit */ |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int stop_ppp_connect(PPP_CTX *ppp_ctx) |
| | | { |
| | | log_warn("Stop PPP connection now.\n"); |
| | | |
| | | if(check_ppp_interface(ppp_ctx->dev)) |
| | | return 0; |
| | | |
| | | kill_pppd_process(ppp_ctx->comport); |
| | | |
| | | if(ppp_ctx->comport) |
| | | { |
| | | free_gsm_dataport("stop_ppp_connect()", ppp_ctx->module, &(ppp_ctx->comport)); |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | int get_apn_conf(char *ini_name, char *ini_key, APN_ACCOUNT *apn, unsigned char type) |
| | | { |
| | | dictionary *ini ; |
| | | char tmp[64]; |
| | | char *str; |
| | | |
| | | if(NULL==ini_name || NULL==ini_key || NULL==apn) |
| | | { |
| | | return -1; |
| | | } |
| | | |
| | | ini = iniparser_load(ini_name); |
| | | if (ini==NULL) |
| | | { |
| | | log_err("cannot load default APN configure file: %s\n", ini_name); |
| | | return -2 ; |
| | | } |
| | | log_dbg("Parser default APN configure file %s\n", ini_name); |
| | | |
| | | /* Parser APN configure */ |
| | | snprintf(tmp, 64, "%s:%s", ini_key, APN_3G==type?"3g_apn":"apn"); |
| | | if( !(str=iniparser_getstring(ini, tmp, NULL)) ) |
| | | { |
| | | log_err("cannot find APN setting for SIM [%s] in file: %s\n", ini_key, ini_name); |
| | | memset(apn, 0, sizeof(APN_ACCOUNT)); |
| | | return -1; |
| | | } |
| | | else |
| | | { |
| | | strncpy(apn->apn, str, APN_LEN); |
| | | } |
| | | |
| | | /* Paser APN username information */ |
| | | snprintf(tmp, 64, "%s:%s", ini_key, APN_3G==type?"3g_uid":"uid"); |
| | | str = iniparser_getstring(ini, tmp, NULL); |
| | | strncpy(apn->uid, str, UID_LEN); |
| | | |
| | | |
| | | /* Paser APN password information */ |
| | | snprintf(tmp, 64, "%s:%s", ini_key, APN_3G==type?"3g_pwd":"pwd"); |
| | | str = iniparser_getstring(ini, tmp, NULL); |
| | | strncpy(apn->pwd, str, PWD_LEN); |
| | | |
| | | iniparser_freedict(ini); |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | int select_apn(PPP_CTX *ppp_ctx, char *key) |
| | | { |
| | | int retval; |
| | | unsigned char type = APN_2G; |
| | | |
| | | log_nrml("GPRS module work on GPRS mode, select APN now.\n"); |
| | | |
| | | retval = get_apn_conf(APN_DEF_CONF_FILE, key, &(ppp_ctx->apn), type); |
| | | if(!retval) |
| | | { |
| | | log_err("Get default APN [%s] from %s ok\n", ppp_ctx->apn.apn, APN_DEF_CONF_FILE); |
| | | return 0; |
| | | } |
| | | |
| | | return -1; |
| | | } |
| | | |
| | | #define PPPD_CMD_LEN 512 |
| | | int start_ppp_dial_cmd(COM_PORT *comport, APN_ACCOUNT *apn, char *ppp_dev) |
| | | { |
| | | char tmp[64]; |
| | | char pppd_cmd[PPPD_CMD_LEN]; |
| | | pid_t pid; |
| | | |
| | | if( !comport || !comport->is_connted ) |
| | | { |
| | | log_err("GPRS module data port %s is not opened.\n", comport->dev_name); |
| | | return -1; |
| | | } |
| | | |
| | | if( !apn || strlen(apn->apn)<=0 ) |
| | | { |
| | | log_err("No valid APN was set.\n"); |
| | | return -1; |
| | | } |
| | | |
| | | log_nrml("Start PPP connection with APN \"%s\" now.\n", apn->apn); |
| | | |
| | | memset(pppd_cmd, 0, PPPD_CMD_LEN); |
| | | snprintf(pppd_cmd, PPPD_CMD_LEN, "%s -d %s ", PPPD_DIAL_SCRIPTS, comport->dev_name); |
| | | |
| | | snprintf(tmp, sizeof(tmp), " -a %s ", apn->apn); |
| | | strncat(pppd_cmd, tmp, PPPD_CMD_LEN); |
| | | |
| | | if( strlen(apn->uid) > 0 ) |
| | | { |
| | | snprintf(tmp, sizeof(tmp), " -u %s ", apn->uid); |
| | | strncat(pppd_cmd, tmp, PPPD_CMD_LEN); |
| | | } |
| | | |
| | | if( strlen(apn->pwd) > 0 ) |
| | | { |
| | | snprintf(tmp, sizeof(tmp), " -p %s ", apn->pwd); |
| | | strncat(pppd_cmd, tmp, PPPD_CMD_LEN); |
| | | } |
| | | |
| | | if( strlen(apn->auth) > 0 ) |
| | | { |
| | | snprintf(tmp, sizeof(tmp), " -v %s ", apn->auth); |
| | | strncat(pppd_cmd, tmp, PPPD_CMD_LEN); |
| | | } |
| | | |
| | | strncat(pppd_cmd, ppp_dev, PPPD_CMD_LEN); |
| | | |
| | | log_nrml("ppp dial up command: %s\n", pppd_cmd); |
| | | |
| | | pid = fork(); |
| | | if( 0 == pid ) /* Child process */ |
| | | { |
| | | system(pppd_cmd); |
| | | exit(0); |
| | | } |
| | | else if (pid < 0) |
| | | { |
| | | log_err("Create new process failure.\n"); |
| | | return -1; |
| | | } |
| | | else |
| | | { |
| | | log_dbg("pppd program already running.\n"); |
| | | micro_second_sleep(1000); |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int check_pppd_pid(char *find_key) |
| | | { |
| | | char buf[10]; |
| | | char cmd[128]; |
| | | FILE *fp = NULL; |
| | | int pid = -1; |
| | | |
| | | snprintf(cmd, sizeof(cmd), "ps | grep -v grep | grep pppd | grep %s | awk '{print $1}'", find_key); |
| | | |
| | | fp = popen(cmd, "r"); |
| | | if(NULL == fp) |
| | | { |
| | | log_fatal("popen() to check the pppd process ID failure.\n"); |
| | | return -1; |
| | | } |
| | | |
| | | memset(buf, 0, sizeof(buf)); |
| | | fgets(buf, sizeof(buf), fp); |
| | | |
| | | pid = atoi(buf); |
| | | |
| | | if(pid <= 1) |
| | | { |
| | | log_err("Get pppd program running pid failure\n"); |
| | | pid = -1; |
| | | } |
| | | #if 0 |
| | | else |
| | | { |
| | | log_trace("pppd program running pid is [%d]\n", pid); |
| | | } |
| | | #endif |
| | | |
| | | pclose(fp); |
| | | return pid; |
| | | } |
| | | |
| | | void set_ppp_disconnect(PPP_CTX *ppp_ctx) |
| | | { |
| | | ppp_ctx->status = DISCONNECT; |
| | | ppp_ctx->pppd_info.start_time = 0; |
| | | |
| | | memset(&(ppp_ctx->pppd_info), 0, sizeof(PPPD_INFO)); |
| | | memset(&(ppp_ctx->ppp_stat), 0, sizeof(PPP_STAT)); |
| | | ppp_ctx->network = PPP_STOP; |
| | | } |
| | | |
| | | |
| | | int ppp_context_init(PPP_CTX *ppp_ctx, MODULE_INFO *module) |
| | | { |
| | | memset(ppp_ctx, 0, sizeof(*ppp_ctx)); |
| | | |
| | | ppp_ctx->thread_id = pthread_self(); |
| | | ppp_ctx->module = module; |
| | | strncpy(ppp_ctx->dev, PPP_INTERFACE_NAME, sizeof(ppp_ctx->dev)); |
| | | strncpy(ppp_ctx->ping_ip, DEF_PING_DST, sizeof(ppp_ctx->ping_ip)); |
| | | ppp_ctx->ping_interval = PING_INTERVAL_TIME; |
| | | set_ppp_disconnect(ppp_ctx); |
| | | |
| | | log_nrml("Initialize PPP thread context ok\n"); |
| | | return 0; |
| | | } |
| | | |
| | | void ppp_context_term(PPP_CTX *ppp_ctx) |
| | | { |
| | | stop_ppp_connect(ppp_ctx); |
| | | set_ppp_disconnect(ppp_ctx); |
| | | |
| | | log_nrml("Terminate PPP thread context ok\n"); |
| | | } |
| | | |
| | | int start_ppp_connect(PPP_CTX *ppp_ctx) |
| | | { |
| | | int retval; |
| | | MODULE_INFO *module = ppp_ctx->module; |
| | | |
| | | if( !ppp_ctx->comport ) |
| | | { |
| | | ppp_ctx->comport=alloc_gsm_dataport("start_ppp_connect()", ppp_ctx->module); |
| | | if(!ppp_ctx->comport) |
| | | return -1; |
| | | |
| | | log_dbg("PPP thread alloc GPRS dataport %s=>[fd:%d]\n", ppp_ctx->comport->dev_name, ppp_ctx->comport->fd); |
| | | } |
| | | |
| | | |
| | | switch(ppp_ctx->status) |
| | | { |
| | | case DISCONNECT: /* Select the APN now */ |
| | | set_ppp_disconnect(ppp_ctx); |
| | | retval = select_apn(ppp_ctx, module->reg.loc.mcc_mnc); |
| | | if(!retval) |
| | | { |
| | | log_nrml("Select APN successfully, go to next stage.\n"); |
| | | ppp_ctx->fail_cnt = 0; |
| | | ppp_ctx->status++; |
| | | } |
| | | else |
| | | { |
| | | log_warn("Select APN failure, request to reset GPRS module\n"); |
| | | ppp_ctx->fail_cnt ++; |
| | | set_module_event(module, REQ_POWER_RESET); |
| | | break; |
| | | } |
| | | |
| | | case SELECTED_APN: /* Select the APN now */ |
| | | log_warn("Run pppd program to start PPP connection now\n"); |
| | | ppp_ctx->network = PPP_CONN; |
| | | start_ppp_dial_cmd(ppp_ctx->comport, &(ppp_ctx->apn), ppp_ctx->dev); |
| | | ppp_ctx->status++; |
| | | break; |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int inspect_network_status(PPP_CTX *ppp_ctx) |
| | | { |
| | | PPPD_INFO *pppd_info = &(ppp_ctx->pppd_info); |
| | | PPP_STAT *ppp_stat = &(ppp_ctx->ppp_stat); |
| | | int lost_percent; |
| | | unsigned long long last_tx_bytes= ppp_stat->ullTx_Bytes; |
| | | unsigned long long last_rx_bytes= ppp_stat->ullRx_Bytes; |
| | | |
| | | if( CONNECTED != ppp_ctx->status) |
| | | { |
| | | ppp_ctx->pppd_info.ping_time = 0; |
| | | memset(ppp_stat, 0, sizeof(PPP_STAT)); |
| | | |
| | | pppd_info->pid = check_pppd_pid(ppp_ctx->comport->dev_name); |
| | | if(pppd_info->pid <= 0) |
| | | { |
| | | /* pppd can not connect in 30s, then set it to DISCONNECT status */ |
| | | if(time_elapsed(pppd_info->start_time) >= PPPD_DIAL_TIMEOUT) |
| | | { |
| | | /* Sleep for 2 seconds, make sure the exit pppd process release the TTY device */ |
| | | micro_second_sleep(2000); |
| | | log_err("pppd process exit when do ppp dialing, set status to DISCONNECT.\n"); |
| | | set_ppp_disconnect(ppp_ctx); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | if(strlen(pppd_info->netaddr) <=0 ) |
| | | { |
| | | check_ppp_ipaddr(pppd_info, ppp_ctx->dev); |
| | | log_dbg("pppd running process ID [%d].\n", pppd_info->pid); |
| | | } |
| | | } |
| | | } |
| | | |
| | | if( time_elapsed(pppd_info->ping_time) >= ppp_ctx->ping_interval*1000 ) |
| | | { |
| | | if(ppp_ctx->fail_cnt >= MAX_PPP_FAIL_CNT) |
| | | { |
| | | /* Sleep for 2 seconds, make sure the exit pppd process release the TTY device */ |
| | | micro_second_sleep(2000); |
| | | log_warn("PPP network inspect status failure, set status to DISCONNECT.\n"); |
| | | set_ppp_disconnect(ppp_ctx); |
| | | return 0; |
| | | } |
| | | |
| | | lost_percent = network_ping_test(ppp_ctx->dev, ppp_ctx->ping_ip); |
| | | ppp_ctx->network = lost_percent<=60 ? PPP_GOOD : PPP_BAD; |
| | | |
| | | if(lost_percent <= 80) |
| | | { |
| | | check_ppp_stat(ppp_stat, ppp_ctx->dev); |
| | | if(last_tx_bytes==ppp_stat->ullTx_Bytes || last_rx_bytes==ppp_stat->ullRx_Bytes) |
| | | { |
| | | log_warn("PPP interface traffic not increased, maybe ppp disconnected?\n"); |
| | | ppp_ctx->fail_cnt++; |
| | | } |
| | | else |
| | | { |
| | | log_nrml("Set PPP connection status to CONNECTED.\n"); |
| | | set_ppp_disconnect(ppp_ctx); |
| | | ppp_ctx->fail_cnt=0; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | ppp_ctx->fail_cnt++; |
| | | } |
| | | ppp_ctx->pppd_info.ping_time = time_now(); |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | void *ppp_thread_workbody(void *thread_arg) |
| | | { |
| | | PPP_CTX ppp_ctx; |
| | | |
| | | MODULE_INFO *module; |
| | | |
| | | module = (MODULE_INFO *)thread_arg; |
| | | ppp_context_init(&ppp_ctx, module); |
| | | |
| | | log_nrml("GPRS PPP thread start running\n"); |
| | | |
| | | while( !g_cp_signal.stop ) |
| | | { |
| | | if(ALL_READY != module->ready) |
| | | { |
| | | if(ppp_ctx.status>=CONNECTING) |
| | | { |
| | | log_nrml("Stop exist PPP connection and free TTY data port\n"); |
| | | stop_ppp_connect(&ppp_ctx); |
| | | } |
| | | |
| | | /* GPRS not ready, sleep for 200ms and check again */ |
| | | micro_second_sleep(200); |
| | | continue; |
| | | } |
| | | else |
| | | { |
| | | if(ppp_ctx.status>=CONNECTING) |
| | | { |
| | | inspect_network_status(&ppp_ctx); |
| | | } |
| | | else |
| | | { |
| | | start_ppp_connect(&ppp_ctx); |
| | | } |
| | | } |
| | | |
| | | sleep(1); |
| | | } |
| | | |
| | | ppp_context_term(&ppp_ctx); |
| | | pthread_exit(0); |
| | | return NULL; |
| | | } |
| | | |
| | | int start_thread_ppp(MODULE_INFO *module) |
| | | { |
| | | pthread_t tid; |
| | | |
| | | return thread_start(&tid, ppp_thread_workbody, module); |
| | | } |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) guowenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: ppp.h |
| | | * Description: This head file is for PPP dial up thread. |
| | | * |
| | | * Version: 1.0.0(02/17/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "02/17/2012 11:11:54 AM" |
| | | * |
| | | ********************************************************************************/ |
| | | #ifndef __PPP_H |
| | | #define __PPP_H |
| | | |
| | | #include <netinet/in.h> |
| | | |
| | | #include "cp_comport.h" |
| | | #include "cp_proc.h" |
| | | #include "cp_gprs.h" |
| | | |
| | | #define PPPD_DIAL_TIMEOUT 20000 /* 20 seconds */ |
| | | #define PING_INTERVAL_TIME 10000 /* 10 seconds */ |
| | | |
| | | #define DEFAULT_PING_INTERVAL 30 |
| | | #define APN_LEN 128 |
| | | #define UID_LEN 64 |
| | | #define PWD_LEN 64 |
| | | |
| | | #define APN_3G 3 |
| | | #define APN_2G 2 |
| | | |
| | | #define PPPD_DIAL_SCRIPTS "/apps/tools/ifup-ppp" |
| | | #define PPP_INTERFACE_NAME "ppp10" |
| | | #define PPP_PROC_NET_DEV "/proc/net/dev" |
| | | |
| | | #define DEF_PING_DST "4.2.2.2" |
| | | |
| | | #define APN_DEF_CONF_FILE "/apps/etc/ppp/default_apn.conf" |
| | | |
| | | enum |
| | | { |
| | | DISCONNECT = 0, |
| | | SELECTED_APN, |
| | | CONNECTING, |
| | | CONNECTED, |
| | | }; |
| | | |
| | | |
| | | typedef struct __APN_ACCOUNT |
| | | { |
| | | char apn[APN_LEN]; |
| | | char uid[UID_LEN]; |
| | | char pwd[PWD_LEN]; |
| | | char auth[10]; /* PAP or CHAP */ |
| | | } APN_ACCOUNT; |
| | | |
| | | typedef struct __PPPD_INFO |
| | | { |
| | | char netaddr[INET_ADDRSTRLEN]; |
| | | char ptpaddr[INET_ADDRSTRLEN]; |
| | | unsigned long start_time; |
| | | unsigned long ping_time; |
| | | pid_t pid; |
| | | } PPPD_INFO; |
| | | |
| | | typedef struct __PPP_STAT |
| | | { |
| | | unsigned long long ullRx_Packets; // total packets received |
| | | unsigned long long ullTx_Packets; // total packets transmitted |
| | | unsigned long long ullRx_Bytes; // total bytes received |
| | | unsigned long long ullTx_Bytes; // total bytes transmitted |
| | | |
| | | unsigned long ulRx_Errors; // bad packets received |
| | | unsigned long ulTx_Errors; // packet transmit problems |
| | | unsigned long ulRx_Dropped; // no space in linux buffers |
| | | unsigned long ulTx_Dropped; // no space available in linux |
| | | unsigned long ulRx_Multicast; // multicast packets received |
| | | unsigned long ulRx_Compressed; |
| | | unsigned long ulTx_Compressed; |
| | | unsigned long ulCollisions; |
| | | |
| | | /* detailed rx_errors */ |
| | | unsigned long ulRx_Length_Errors; |
| | | unsigned long ulRx_Over_Errors; // receiver ring buff overflow |
| | | unsigned long ulRx_CRC_Errors; // recved pkt with crc error |
| | | unsigned long ulRx_Frame_Errors; // recv'd frame alignment error |
| | | unsigned long ulRx_FIFO_Errors; // recv'r fifo overrun |
| | | unsigned long ulRx_Missed_Errors; // receiver missed packet |
| | | |
| | | /* detailed tx_errors */ |
| | | unsigned long ulTx_Aborted_Errors; |
| | | unsigned long ulTx_Carrier_Errors; |
| | | unsigned long ulTx_FIFO_Errors; |
| | | unsigned long ulTx_Heartbeat_Errors; |
| | | unsigned long ulTx_Window_Errors; |
| | | } PPP_STAT; |
| | | |
| | | #define MAX_PPP_FAIL_CNT 3 |
| | | |
| | | #define PPP_STOP 0 /* PPP not work, but signal good */ |
| | | #define SIG_WEAK 1 /* PPP not work and signal is very weak */ |
| | | #define PPP_CONN 2 /* PPP is connecting */ |
| | | #define PPP_BAD 3 /* PPP is connected, but network/signal not good */ |
| | | #define PPP_GOOD 4 /* PPP is connected and network/signal good */ |
| | | typedef struct __PPP_CTX |
| | | { |
| | | unsigned char enable; /* Enable PPP thread running or not, RFU */ |
| | | unsigned char status; /* Current PPP connection status */ |
| | | unsigned char network; /* PPP network status: PPP_FAIL,PPP_BAD,PPP_GOOD */ |
| | | char dev[10]; /* PPP dial up device name, such as PPP10 */ |
| | | |
| | | pthread_t thread_id; /* PPP Thread ID, RFU */ |
| | | |
| | | PPPD_INFO pppd_info; /* pppd process information */ |
| | | PPP_STAT ppp_stat; /* PPP network statistic */ |
| | | unsigned char fail_cnt; /* PPP failure count */ |
| | | |
| | | APN_ACCOUNT apn; /* PPP dial up APN */ |
| | | |
| | | char ping_ip[INET_ADDRSTRLEN]; |
| | | long ping_interval; |
| | | |
| | | COM_PORT *comport; |
| | | MODULE_INFO *module; |
| | | } PPP_CTX; |
| | | |
| | | int get_apn_conf(char *ini_name, char *ini_key, APN_ACCOUNT *apn, unsigned char type); |
| | | int check_pppd_pid(char *find_key); |
| | | int check_ppp_interface(char *ppp_inf); |
| | | int start_ppp_dial_cmd(COM_PORT *comport, APN_ACCOUNT *apn, char *ppp_inf); |
| | | int check_ppp_ipaddr(PPPD_INFO *pppd_info, char *ppp_inf); |
| | | int check_ppp_stat(PPP_STAT *ppp_stat, char *ppp_inf); |
| | | int stop_ppp_connect(PPP_CTX *ppp_ctx); |
| | | |
| | | int start_thread_ppp(MODULE_INFO *module); |
| | | |
| | | #endif /* End of __PPP_H */ |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_proc.c |
| | | * Description: This file is the process API |
| | | * |
| | | * Version: 1.0.0(11/06/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "11/06/2012 09:19:02 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <unistd.h> |
| | | #include <libgen.h> |
| | | #include <fcntl.h> |
| | | #include <sys/types.h> |
| | | #include <sys/stat.h> |
| | | |
| | | #include "cp_proc.h" |
| | | #include "cp_logger.h" |
| | | |
| | | CP_PROC_SIG g_cp_signal={0}; |
| | | |
| | | void cp_proc_sighandler(int sig) |
| | | { |
| | | switch(sig) |
| | | { |
| | | case SIGINT: |
| | | log_warn("SIGINT - stopping\n"); |
| | | g_cp_signal.stop = 1; |
| | | break; |
| | | |
| | | case SIGTERM: |
| | | //log_warn("SIGTERM - stopping\n"); |
| | | g_cp_signal.stop = 1; |
| | | break; |
| | | #if 0 |
| | | case SIGSEGV: |
| | | log_err("SIGSEGV - stopping\n"); |
| | | if(g_cp_signal.stop) |
| | | exit(0); |
| | | |
| | | g_cp_signal.stop = 1; |
| | | break; |
| | | #endif |
| | | |
| | | case SIGPIPE: |
| | | log_warn("SIGPIPE - warnning\n"); |
| | | g_cp_signal.stop = 1; |
| | | break; |
| | | |
| | | default: |
| | | break; |
| | | } |
| | | } |
| | | |
| | | |
| | | void cp_install_proc_signal(void) |
| | | { |
| | | struct sigaction sigact, sigign; |
| | | |
| | | log_nrml("Install default signal handler.\n"); |
| | | |
| | | /* Initialize the catch signal structure. */ |
| | | sigemptyset(&sigact.sa_mask); |
| | | sigact.sa_flags = 0; |
| | | sigact.sa_handler = cp_proc_sighandler; |
| | | |
| | | /* Setup the ignore signal. */ |
| | | sigemptyset(&sigign.sa_mask); |
| | | sigign.sa_flags = 0; |
| | | sigign.sa_handler = SIG_IGN; |
| | | |
| | | sigaction(SIGTERM, &sigact, 0); /* catch terminate signal "kill" command */ |
| | | sigaction(SIGINT, &sigact, 0); /* catch interrupt signal CTRL+C */ |
| | | //sigaction(SIGSEGV, &sigact, 0); /* catch segmentation faults */ |
| | | sigaction(SIGPIPE, &sigact, 0); /* catch broken pipe */ |
| | | #if 0 |
| | | sigaction(SIGCHLD, &sigact, 0); /* catch child process return */ |
| | | sigaction(SIGUSR2, &sigact, 0); /* catch USER signal */ |
| | | #endif |
| | | } |
| | | |
| | | |
| | | /* **************************************************************************** |
| | | * FunctionName: daemonize |
| | | * Description : Set the programe runs as daemon in background |
| | | * Inputs : nodir: DON'T change the work directory to / : 1:NoChange 0:Change |
| | | * noclose: close the opened file descrtipion or not 1:Noclose 0:Close |
| | | * Output : NONE |
| | | * Return : NONE |
| | | * *****************************************************************************/ |
| | | void daemonize(int nochdir, int noclose) |
| | | { |
| | | int retval, fd; |
| | | int i; |
| | | |
| | | /* already a daemon */ |
| | | if (1 == getppid()) |
| | | return; |
| | | |
| | | /* fork error */ |
| | | retval = fork(); |
| | | if (retval < 0) exit(1); |
| | | |
| | | /* parent process exit */ |
| | | if (retval > 0) |
| | | exit(0); |
| | | |
| | | /* obtain a new process session group */ |
| | | setsid(); |
| | | |
| | | if (!noclose) |
| | | { |
| | | /* close all descriptors */ |
| | | for (i = getdtablesize(); i >= 0; --i) |
| | | { |
| | | //if (i != g_logPtr->fd) |
| | | close(i); |
| | | } |
| | | |
| | | /* Redirect Standard input [0] to /dev/null */ |
| | | fd = open("/dev/null", O_RDWR); |
| | | |
| | | /* Redirect Standard output [1] to /dev/null */ |
| | | dup(fd); |
| | | |
| | | /* Redirect Standard error [2] to /dev/null */ |
| | | dup(fd); |
| | | } |
| | | |
| | | umask(0); |
| | | |
| | | if (!nochdir) |
| | | chdir("/"); |
| | | |
| | | return; |
| | | } |
| | | |
| | | /* **************************************************************************** |
| | | * FunctionName: record_daemon_pid |
| | | * Description : Record the running daemon program PID to the file "pid_file" |
| | | * Inputs : pid_file:The record PID file path |
| | | * Output : NONE |
| | | * Return : 0: Record successfully Else: Failure |
| | | * *****************************************************************************/ |
| | | int record_daemon_pid(const char *pid_file) |
| | | { |
| | | struct stat fStatBuf; |
| | | int fd = -1; |
| | | int mode = S_IROTH | S_IXOTH | S_IRGRP | S_IXGRP | S_IRWXU; |
| | | char ipc_dir[64] = { 0 }; |
| | | |
| | | strncpy(ipc_dir, pid_file, 64); |
| | | |
| | | /* dirname() will modify ipc_dir and save the result */ |
| | | dirname(ipc_dir); |
| | | |
| | | /* If folder pid_file PATH doesnot exist, then we will create it" */ |
| | | if (stat(ipc_dir, &fStatBuf) < 0) |
| | | { |
| | | if (mkdir(ipc_dir, mode) < 0) |
| | | { |
| | | log_fatal("cannot create %s: %s\n", ipc_dir, strerror(errno)); |
| | | return -1; |
| | | } |
| | | |
| | | (void)chmod(ipc_dir, mode); |
| | | } |
| | | |
| | | /* Create the process running PID file */ |
| | | mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; |
| | | if ((fd = open(pid_file, O_RDWR | O_CREAT | O_TRUNC, mode)) >= 0) |
| | | { |
| | | char pid[PID_ASCII_SIZE]; |
| | | snprintf(pid, sizeof(pid), "%u\n", (unsigned)getpid()); |
| | | write(fd, pid, strlen(pid)); |
| | | close(fd); |
| | | |
| | | log_dbg("Record PID<%u> to file %s.\n", getpid(), pid_file); |
| | | } |
| | | else |
| | | { |
| | | log_fatal("cannot create %s: %s\n", pid_file, strerror(errno)); |
| | | return -1; |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | /* **************************************************************************** |
| | | * FunctionName: get_daemon_pid |
| | | * Description : Get the daemon process PID from the PID record file "pid_file" |
| | | * Inputs : pid_file: the PID record file |
| | | * Output : NONE |
| | | * Return : pid_t: The daemon process PID number |
| | | * *****************************************************************************/ |
| | | pid_t get_daemon_pid(const char *pid_file) |
| | | { |
| | | FILE *f; |
| | | pid_t pid; |
| | | |
| | | if ((f = fopen(pid_file, "rb")) != NULL) |
| | | { |
| | | char pid_ascii[PID_ASCII_SIZE]; |
| | | (void)fgets(pid_ascii, PID_ASCII_SIZE, f); |
| | | (void)fclose(f); |
| | | pid = atoi(pid_ascii); |
| | | } |
| | | else |
| | | { |
| | | log_fatal("Can't open PID record file %s: %s\n", pid_file, strerror(errno)); |
| | | return -1; |
| | | } |
| | | return pid; |
| | | } |
| | | |
| | | /* **************************************************************************** |
| | | * FunctionName: check_daemon_running |
| | | * Description : Check the daemon program already running or not |
| | | * Inputs : pid_file: The record running daemon program PID |
| | | * Output : NONE |
| | | * Return : 1: The daemon program alread running 0: Not running |
| | | * *****************************************************************************/ |
| | | int check_daemon_running(const char *pid_file) |
| | | { |
| | | int retVal = -1; |
| | | struct stat fStatBuf; |
| | | |
| | | retVal = stat(pid_file, &fStatBuf); |
| | | if (0 == retVal) |
| | | { |
| | | pid_t pid = -1; |
| | | printf("PID record file \"%s\" exist.\n", pid_file); |
| | | |
| | | pid = get_daemon_pid(pid_file); |
| | | if (pid > 0) /* Process pid exist */ |
| | | { |
| | | if ((retVal = kill(pid, 0)) == 0) |
| | | { |
| | | printf("Program with PID[%d] seems running.\n", pid); |
| | | return 1; |
| | | } |
| | | else /* Send signal to the old process get no reply. */ |
| | | { |
| | | printf("Program with PID[%d] seems exit.\n", pid); |
| | | remove(pid_file); |
| | | return 0; |
| | | } |
| | | } |
| | | else if (0 == pid) |
| | | { |
| | | printf("Can not read program PID form record file.\n"); |
| | | remove(pid_file); |
| | | return 0; |
| | | } |
| | | else /* Read pid from file "pid_file" failure */ |
| | | { |
| | | printf("Read record file \"%s\" failure, maybe program still running.\n", pid_file); |
| | | return 1; |
| | | } |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | /* **************************************************************************** |
| | | * FunctionName: set_daemon_running |
| | | * Description : Set the programe running as daemon if it's not running and record |
| | | * its PID to the pid_file. |
| | | * Inputs : pid_file: The record running daemon program PID |
| | | * Output : NONE |
| | | * Return : 0: Successfully. 1: Failure |
| | | * *****************************************************************************/ |
| | | int set_daemon_running(const char *pid_file) |
| | | { |
| | | daemonize(0, 1); |
| | | log_nrml("Program running as daemon [PID:%d].\n", getpid()); |
| | | |
| | | if (record_daemon_pid(pid_file) < 0) |
| | | { |
| | | log_fatal("Record PID to file \"%s\" failure.\n", pid_file); |
| | | return -2; |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | int thread_start(pthread_t * thread_id, THREAD_BODY * thread_workbody, void *thread_arg) |
| | | { |
| | | int retval = 0; |
| | | |
| | | pthread_attr_t thread_attr; |
| | | |
| | | /* Initialize the thread attribute */ |
| | | retval = pthread_attr_init(&thread_attr); |
| | | if(retval) |
| | | return -1; |
| | | |
| | | /* Set the stack size of the thread */ |
| | | retval = pthread_attr_setstacksize(&thread_attr, 120 * 1024); |
| | | if(retval) |
| | | goto CleanUp; |
| | | |
| | | /* Set thread to detached state:Don`t need pthread_join */ |
| | | retval = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); |
| | | if(retval) |
| | | goto CleanUp; |
| | | |
| | | /* Create the thread */ |
| | | retval = pthread_create(thread_id, &thread_attr, thread_workbody, thread_arg); |
| | | if(retval) |
| | | goto CleanUp; |
| | | |
| | | CleanUp: |
| | | /* Destroy the attributes of thread */ |
| | | pthread_attr_destroy(&thread_attr); |
| | | return retval; |
| | | } |
| | | |
| | | |
| | | void exec_system_cmd(const char *format, ...) |
| | | { |
| | | char cmd[256]; |
| | | va_list args; |
| | | int done; |
| | | |
| | | memset(cmd, 0, sizeof(cmd)); |
| | | |
| | | va_start(args, format); |
| | | done = vsnprintf(cmd, sizeof(cmd), format, args); |
| | | va_end(args); |
| | | |
| | | system(cmd); |
| | | } |
| | | |
| | | |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_proc.h |
| | | * Description: This head file is for Linux process API |
| | | * |
| | | * Version: 1.0.0(11/06/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "11/06/2012 09:21:33 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #ifndef __CP_PROC_H |
| | | #define __CP_PROC_H |
| | | |
| | | #include <signal.h> |
| | | |
| | | #define PID_ASCII_SIZE 11 |
| | | |
| | | typedef struct __CP_PROC_SIG |
| | | { |
| | | int signal; |
| | | unsigned stop; /* 0: Not term 1: Stop */ |
| | | } CP_PROC_SIG; |
| | | |
| | | typedef void *(THREAD_BODY) (void *thread_arg); |
| | | |
| | | extern CP_PROC_SIG g_cp_signal; |
| | | extern void cp_install_proc_signal(void); |
| | | |
| | | extern void daemonize(int nochdir, int noclose); |
| | | extern int record_daemon_pid(const char *pid_file); |
| | | extern pid_t get_daemon_pid(const char *pid_file); |
| | | extern int check_daemon_running(const char *pid_file); |
| | | extern int set_daemon_running(const char *pid_file); |
| | | |
| | | extern void exec_system_cmd(const char *format, ...); |
| | | |
| | | extern int thread_start(pthread_t * thread_id, THREAD_BODY * thread_workbody, void *thread_arg); |
| | | |
| | | #endif |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_queue.c |
| | | * Description: This file is the queue implement based on link list. |
| | | * |
| | | * Version: 1.0.0(11/12/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "11/12/2012 01:25:26 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include "cp_queue.h" |
| | | #include "cp_common.h" |
| | | |
| | | CP_QUEUE *cp_queue_init(CP_QUEUE *queue, int size) |
| | | { |
| | | if(!queue) |
| | | { |
| | | queue = t_malloc(sizeof(*queue)); |
| | | } |
| | | memset(queue, 0, sizeof(*queue)); |
| | | |
| | | queue->size = size; |
| | | queue->items = 0; |
| | | queue->rear = queue->front = NULL; |
| | | |
| | | return queue; |
| | | } |
| | | |
| | | void *cp_enqueue(CP_QUEUE *queue, void *data) |
| | | { |
| | | CP_QNODE *node; |
| | | |
| | | if(!queue || cp_queue_is_full(queue)) |
| | | { |
| | | return NULL; |
| | | } |
| | | |
| | | node = t_malloc(sizeof(*node)); |
| | | if(NULL == node) |
| | | { |
| | | return NULL; |
| | | } |
| | | |
| | | node->item = data; |
| | | node->next = NULL; |
| | | |
| | | if(cp_queue_is_empty(queue)) |
| | | { |
| | | queue->front = node; |
| | | } |
| | | else |
| | | { |
| | | queue->rear->next = node; |
| | | } |
| | | |
| | | queue->rear = node; |
| | | queue->items++; |
| | | |
| | | return data; |
| | | } |
| | | |
| | | void cp_travel_queue(CP_QUEUE *queue) |
| | | { |
| | | CP_QNODE *node; |
| | | |
| | | for(node=queue->front; node!=NULL; node=node->next) |
| | | { |
| | | printf("queue node[%p] save data [%p]\n", node, node->item); |
| | | } |
| | | } |
| | | |
| | | void *cp_rmqueue(CP_QUEUE *queue, void *data) |
| | | { |
| | | CP_QNODE *node, *tmp; |
| | | |
| | | if(!queue || cp_queue_is_empty(queue)) |
| | | { |
| | | return NULL; |
| | | } |
| | | |
| | | /* The first node->item is the data, we find it */ |
| | | if(queue->front->item==data) |
| | | { |
| | | tmp = queue->front; |
| | | queue->front = queue->front->next; |
| | | queue->items -= 1; |
| | | t_free(tmp); |
| | | return data; |
| | | } |
| | | |
| | | for(node=queue->front; node!=NULL; node=node->next) |
| | | { |
| | | if(node->next->item == data) |
| | | { |
| | | tmp = node->next; |
| | | queue->items -= 1; |
| | | |
| | | if(node->next != queue->rear) |
| | | node->next = node->next->next; |
| | | else |
| | | { |
| | | queue->rear = node; |
| | | queue->rear->next = NULL; |
| | | } |
| | | |
| | | t_free(tmp); |
| | | return data; |
| | | } |
| | | } |
| | | |
| | | return data; |
| | | } |
| | | |
| | | void *cp_dequeue(CP_QUEUE *queue) |
| | | { |
| | | CP_QNODE *node; |
| | | void *item; |
| | | |
| | | if(!queue || cp_queue_is_empty(queue)) |
| | | { |
| | | return NULL; |
| | | } |
| | | |
| | | node = queue->front; |
| | | queue->front = queue->front->next; |
| | | |
| | | item = node->item; |
| | | t_free(node); |
| | | |
| | | queue->items--; |
| | | |
| | | if(queue->items == 0) |
| | | queue->rear = NULL; |
| | | |
| | | return item; |
| | | } |
| | | |
| | | void cp_queue_destroy(CP_QUEUE *queue) |
| | | { |
| | | if(!queue) |
| | | return ; |
| | | |
| | | while( !cp_queue_is_empty(queue) ) |
| | | { |
| | | cp_dequeue(queue); |
| | | } |
| | | |
| | | t_free(queue); |
| | | |
| | | return ; |
| | | } |
| | | |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_queue.h |
| | | * Description: This head file is for the queue implement based on link list. |
| | | * |
| | | * Version: 1.0.0(11/12/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "11/12/2012 01:26:34 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | #ifndef __CP_QUEUE |
| | | #define __CP_QUEUE |
| | | |
| | | #include <stdio.h> |
| | | #include <unistd.h> |
| | | #include <stdlib.h> |
| | | #include <string.h> |
| | | |
| | | typedef struct _CP_QNODE |
| | | { |
| | | void *item; |
| | | struct _CP_QNODE *next; |
| | | } CP_QNODE; |
| | | |
| | | |
| | | typedef struct _CP_QUEUE |
| | | { |
| | | CP_QNODE *front; |
| | | CP_QNODE *rear; |
| | | int items; |
| | | int size; |
| | | } CP_QUEUE; |
| | | |
| | | #define cp_queue_is_full(pq) ( (pq)->size==(pq)->items ? 1 :0 ) |
| | | #define cp_queue_is_empty(pq) ( 0==(pq)->items ? 1 : 0) |
| | | #define cp_queue_count(pq) ( (pq)->items ) |
| | | #define cp_queue_size(pq) ( (pq)->size ) |
| | | |
| | | CP_QUEUE *cp_queue_init(CP_QUEUE *queue, int size); |
| | | void *cp_enqueue(CP_QUEUE *queue, void *data); |
| | | void cp_travel_queue(CP_QUEUE *queue); |
| | | void *cp_rmqueue(CP_QUEUE *queue, void *data); |
| | | void *cp_dequeue(CP_QUEUE *queue); |
| | | void cp_queue_destroy(CP_QUEUE *queue); |
| | | #define cp_queue_destroy_clear(queue) {cp_queue_destroy(queue); queue=NULL;} |
| | | |
| | | #endif |
New file |
| | |
| | | /* |
| | | This program is free software; you can redistribute it and/or modify |
| | | it under the terms of the GNU General Public License as published by |
| | | the Free Software Foundation; either version 2 of the License, or |
| | | (at your option) any later version. |
| | | |
| | | This program is distributed in the hope that it will be useful, |
| | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| | | GNU General Public License for more details. |
| | | |
| | | You should have received a copy of the GNU General Public License |
| | | along with this program; if not, write to the Free Software |
| | | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| | | |
| | | Based on ringbuffer.c by Patrick Prasse (patrick.prasse@gmx.net). Code |
| | | has been modified by Telenor and Gemalto. |
| | | |
| | | */ |
| | | |
| | | |
| | | #include <string.h> |
| | | #include <assert.h> |
| | | #include "cp_ringbuf.h" |
| | | |
| | | void rb_init (struct ring_buffer *ring, u_char* buff, int size) { |
| | | memset (ring, 0, sizeof (struct ring_buffer)); |
| | | ring->rd_pointer = 0; |
| | | ring->wr_pointer = 0; |
| | | ring->buffer= buff; |
| | | ring->size = size; |
| | | } |
| | | |
| | | int |
| | | rb_write (struct ring_buffer *rb, u_char * buf, int len) |
| | | { |
| | | int total; |
| | | int i; |
| | | |
| | | /* total = len = min(space, len) */ |
| | | total = rb_free_size(rb); |
| | | if(len > total) |
| | | len = total; |
| | | else |
| | | total = len; |
| | | |
| | | i = rb->wr_pointer; |
| | | if(i + len > rb->size) |
| | | { |
| | | memcpy(rb->buffer + i, buf, rb->size - i); |
| | | buf += rb->size - i; |
| | | len -= rb->size - i; |
| | | i = 0; |
| | | } |
| | | memcpy(rb->buffer + i, buf, len); |
| | | rb->wr_pointer = i + len; |
| | | return total; |
| | | } |
| | | |
| | | int rb_free_size (struct ring_buffer *rb){ |
| | | return (rb->size - 1 - rb_data_size(rb)); |
| | | } |
| | | |
| | | int rb_read (struct ring_buffer *rb, u_char * buf, int max) { |
| | | int total; |
| | | int i; |
| | | /* total = len = min(used, len) */ |
| | | total = rb_data_size(rb); |
| | | |
| | | if(max > total) |
| | | max = total; |
| | | else |
| | | total = max; |
| | | |
| | | i = rb->rd_pointer; |
| | | if(i + max > rb->size) |
| | | { |
| | | memcpy(buf, rb->buffer + i, rb->size - i); |
| | | buf += rb->size - i; |
| | | max -= rb->size - i; |
| | | i = 0; |
| | | } |
| | | memcpy(buf, rb->buffer + i, max); |
| | | rb->rd_pointer = i + max; |
| | | |
| | | return total; |
| | | } |
| | | |
| | | int rb_data_size (struct ring_buffer *rb) { |
| | | return ((rb->wr_pointer - rb->rd_pointer) & (rb->size-1)); |
| | | } |
| | | |
| | | void rb_clear (struct ring_buffer *rb) { |
| | | memset(rb->buffer,0,rb->size); |
| | | rb->rd_pointer=0; |
| | | rb->wr_pointer=0; |
| | | } |
| | | |
| | | u_char rb_peek(struct ring_buffer* rb, int index) { |
| | | assert(index < rb_data_size(rb)); |
| | | |
| | | return rb->buffer[((rb->rd_pointer + index) % rb->size)]; |
| | | } |
New file |
| | |
| | | /* |
| | | This program is free software; you can redistribute it and/or modify |
| | | it under the terms of the GNU General Public License as published by |
| | | the Free Software Foundation; either version 2 of the License, or |
| | | (at your option) any later version. |
| | | |
| | | This program is distributed in the hope that it will be useful, |
| | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| | | GNU General Public License for more details. |
| | | |
| | | You should have received a copy of the GNU General Public License |
| | | along with this program; if not, write to the Free Software |
| | | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| | | |
| | | Based on ringbuffer.h by Patrick Prasse (patrick.prasse@gmx.net). Code |
| | | has been modified by Telenor and Gemalto. |
| | | |
| | | */ |
| | | |
| | | #ifndef __CP_RINGBUF_H_ |
| | | #define __CP_RINGBUF_H_ |
| | | |
| | | #include <sys/types.h> |
| | | |
| | | struct ring_buffer { |
| | | u_char *buffer; |
| | | int wr_pointer; |
| | | int rd_pointer; |
| | | int size; |
| | | }; |
| | | |
| | | /* Initial the ring buffer */ |
| | | void rb_init (struct ring_buffer *ring, u_char* buff, int size) ; |
| | | |
| | | /* Description: Write $len bytes data in $buf into ring buffer $rb |
| | | * Return Value: The actual written into ring buffer data size, if ring buffer |
| | | * left space size small than $len, then only part of the data be written into. |
| | | */ |
| | | int rb_write (struct ring_buffer *rb, u_char * buf, int len) ; |
| | | |
| | | /* Get ring buffer left free size */ |
| | | int rb_free_size (struct ring_buffer *rb); |
| | | |
| | | /* Read $max bytes data from ring buffer $rb to $buf */ |
| | | int rb_read (struct ring_buffer *rb, u_char * buf, int max); |
| | | |
| | | /* Read a specify $index byte data in ring buffer $rb */ |
| | | u_char rb_peek(struct ring_buffer* rb, int index); |
| | | |
| | | /* Get data size in the ring buffer */ |
| | | int rb_data_size (struct ring_buffer *); |
| | | |
| | | /* Clear the ring buffer data */ |
| | | void rb_clear (struct ring_buffer *rb) ; |
| | | |
| | | #endif /* __CP_RINGBUF_H_ */ |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_sock.c |
| | | * Description: This file is the Linux TCP socket basic library. |
| | | * |
| | | * Version: 1.0.0(10/26/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "10/26/2012 01:20:41 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include "cp_sock.h" |
| | | #include "cp_logger.h" |
| | | #include "cp_common.h" |
| | | #include "cp_time.h" |
| | | |
| | | CP_SOCK *cp_sock_init(CP_SOCK *sock, unsigned int rsize, unsigned int ssize, int keepintvl, int keepcnt) |
| | | { |
| | | if(!sock) |
| | | { |
| | | if( !(sock=(CP_SOCK *)t_malloc(sizeof(*sock))) ) |
| | | { |
| | | log_err("socket context malloc failed: %s\n", strerror(errno)); |
| | | goto failed; |
| | | } |
| | | else |
| | | { |
| | | memset(sock, 0, sizeof(*sock)); |
| | | sock->flag |= FLAG_SOCK_MALLOC; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | memset(sock, 0, sizeof(*sock)); |
| | | } |
| | | |
| | | if( !(sock->rbuf=cp_string_create_empty(CP_DEF_RCVBUF_SIZE)) ) |
| | | { |
| | | log_err("socket context create recv buffer failed\n"); |
| | | cp_sock_term(sock); |
| | | goto failed; |
| | | } |
| | | |
| | | if( !(sock->sbuf=cp_string_create_empty(CP_DEF_SNDBUF_SIZE)) ) |
| | | { |
| | | log_err("socket context create send buffer failed\n"); |
| | | cp_sock_term(sock); |
| | | goto failed; |
| | | } |
| | | |
| | | log_dbg("socket context [%p] initialise ok\n", sock); |
| | | sock->rsize = rsize; |
| | | sock->ssize = ssize; |
| | | sock->keepintvl = keepintvl; |
| | | sock->keepcnt = keepcnt; |
| | | sock->idle_timeout = CP_SOCK_DEF_IDLE_TIMEOUT; |
| | | sock->msg_timeout = CP_SOCK_DEF_MSG_TIMEOUT; |
| | | sock->fd = -1; |
| | | sock->index = -1; |
| | | sock->actv_time = time_now(); |
| | | |
| | | sock->flag |= FLAG_SOCK_INIT; |
| | | |
| | | return sock; |
| | | |
| | | failed: |
| | | log_err("socket context initialize failed\n"); |
| | | return NULL; |
| | | } |
| | | |
| | | void cp_sock_term(CP_SOCK *sock) |
| | | { |
| | | if(!sock) |
| | | return; |
| | | |
| | | log_dbg("terminate socket [%p:%d] now\n", sock, sock->fd); |
| | | |
| | | if(sock->flag & FLAG_SOCK_INIT) |
| | | cp_sock_close(sock); |
| | | |
| | | if(sock->rbuf) |
| | | { |
| | | cp_string_destroy(sock->rbuf); |
| | | } |
| | | |
| | | if(sock->privt && sock->privt_free) |
| | | { |
| | | sock->privt_free(); |
| | | } |
| | | |
| | | if(sock->sbuf) |
| | | { |
| | | cp_string_destroy(sock->sbuf); |
| | | } |
| | | |
| | | if(sock->flag & FLAG_SOCK_MALLOC) |
| | | { |
| | | //memset(sock, 0, sizeof(*sock)); |
| | | t_free(sock); |
| | | return ; |
| | | } |
| | | |
| | | //memset(sock, 0, sizeof(*sock)); |
| | | sock->fd = -1; |
| | | |
| | | return ; |
| | | } |
| | | |
| | | int cp_sock_close(CP_SOCK *sock) |
| | | { |
| | | int rv = 0; |
| | | int force = 0; |
| | | |
| | | if(!sock) |
| | | return -1; |
| | | |
| | | if(sock->fd>0) |
| | | { |
| | | log_dbg("Close socket[%d] bind [%s:%d]\n", sock->fd, sock->laddr, sock->lport); |
| | | if(force) |
| | | { |
| | | /* |
| | | * If l_onoff is nonzero and l_linger is zero, TCP aborts the connection when it is closed. |
| | | * That is, TCP discards any data still remaining in the socket send buffer and sends an RST |
| | | * to the peer, not the normal four-packet connection termination sequence. |
| | | */ |
| | | struct linger so_linger; |
| | | |
| | | so_linger.l_onoff = 1; /* Turn on linger */ |
| | | so_linger.l_linger = 0; /* Set the timeout to 0 */ |
| | | |
| | | setsockopt (sock->fd, SOL_SOCKET, SO_LINGER, (char *) &so_linger, sizeof (struct linger)); |
| | | } |
| | | |
| | | if(CP_SOCK_MODE_ACCEPT == sock->mode || CP_SOCK_MODE_CONNECT == sock->mode) |
| | | { |
| | | shutdown (sock->fd, SHUT_RDWR); |
| | | } |
| | | |
| | | if( (rv=close(sock->fd)) ) |
| | | { |
| | | return -2; |
| | | } |
| | | } |
| | | |
| | | sock->fd = -1; |
| | | return rv; |
| | | } |
| | | |
| | | |
| | | int cp_sock_listen(CP_SOCK *sock, char *laddr, int lport, int backlog) |
| | | { |
| | | int rv = 0; |
| | | int fd = -1; |
| | | char service[20]; |
| | | struct addrinfo hints, *rp; |
| | | struct addrinfo *res = NULL; |
| | | struct in_addr inaddr; |
| | | |
| | | if(!sock || !(sock->flag&FLAG_SOCK_INIT) || lport<=0 || backlog <=0) |
| | | { |
| | | log_err("Invalide input arguments\n"); |
| | | rv = -1; |
| | | goto cleanup; |
| | | } |
| | | |
| | | strncpy(sock->laddr, (!laddr?"0.0.0.0":laddr), sizeof(sock->laddr)); |
| | | log_dbg("Create socket listen on [%s:%d] now\n", sock->laddr, lport); |
| | | |
| | | cp_sock_close(sock); |
| | | |
| | | memset(&hints, 0, sizeof(struct addrinfo)); |
| | | hints.ai_family = AF_INET; /* Only support IPv4 */ |
| | | hints.ai_socktype = SOCK_STREAM; |
| | | hints.ai_protocol = IPPROTO_TCP; /* TCP protocol */ |
| | | hints.ai_flags = AI_PASSIVE; |
| | | |
| | | /* If 'laddr' is a valid IP address, then don't use name resolution */ |
| | | if(laddr && inet_aton(laddr, &inaddr)) |
| | | { |
| | | log_info("%s is a valid IP address, don't use name resolution.\n", laddr); |
| | | hints.ai_flags |= AI_NUMERICHOST; |
| | | } |
| | | |
| | | /* Obtain address(es) matching host/port */ |
| | | snprintf(service, sizeof(service), "%d", lport); |
| | | if( (rv=getaddrinfo(laddr, service, &hints, &res)) ) |
| | | { |
| | | log_err("getaddrinfo() parser [%s:%s] failed: %s\n", laddr, service, gai_strerror(rv)); |
| | | rv = -2; |
| | | goto cleanup; |
| | | } |
| | | |
| | | |
| | | /* getaddrinfo() returns a list of address structures. Try each |
| | | * address until we successfully connect or bind*/ |
| | | sock->fd = -1; |
| | | for (rp=res; rp!=NULL; rp=rp->ai_next) |
| | | { |
| | | /* Create the socket */ |
| | | if( (fd=socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) < 0) |
| | | { |
| | | log_err("socket() create failed: %s\n", strerror(errno)); |
| | | rv = -3; |
| | | continue; |
| | | } |
| | | |
| | | cp_sock_set_reuseaddr(fd); |
| | | cp_sock_set_keepalive(fd, sock->keepintvl, sock->keepcnt); |
| | | cp_sock_set_nonblock(fd); |
| | | |
| | | if( 0==bind(fd, rp->ai_addr, rp->ai_addrlen) ) |
| | | { |
| | | struct sockaddr_in *saddr = (struct sockaddr_in *)rp->ai_addr; |
| | | sock->fd = fd; |
| | | sock->lport = lport; |
| | | |
| | | strncpy (sock->laddr, inet_ntoa (saddr->sin_addr), sizeof(sock->laddr)-1); |
| | | log_dbg("Bind socket[%d] ok\n", fd); |
| | | rv = 0; |
| | | break; |
| | | } |
| | | else |
| | | { |
| | | rv = -4; |
| | | log_err("Bind socket[%d] failed: %s\n", fd, strerror(errno)); |
| | | } |
| | | |
| | | close(fd); |
| | | } /* for (rp=res; rp!=NULL; rp=rp->ai_next) */ |
| | | |
| | | |
| | | if(sock->fd < 0) |
| | | { |
| | | close(fd); |
| | | goto cleanup; |
| | | } |
| | | |
| | | if(listen(sock->fd, backlog)) |
| | | { |
| | | log_err("Listen on socket[%d] failed: %s\n", sock->fd, strerror(errno)); |
| | | rv = -6; |
| | | goto cleanup; |
| | | } |
| | | |
| | | sock->mode = CP_SOCK_MODE_LISTEN; |
| | | sock->rport = 0; |
| | | memset(&sock->raddr, 0, sizeof(sock->raddr)); |
| | | |
| | | cleanup: |
| | | if( rv ) |
| | | { |
| | | log_err("Create socket listen on [%s:%d] failed\n", sock->laddr, lport); |
| | | if(sock->fd > 0) |
| | | close(sock->fd); |
| | | } |
| | | else |
| | | { |
| | | sock->actv_time = time_now(); |
| | | sock->status = SOCK_STAT_LISTENED; |
| | | log_nrml("Create socket[%p:%d] listen [%s:%d] ok\n", sock, sock->fd, sock->laddr, lport); |
| | | } |
| | | |
| | | if(res) |
| | | freeaddrinfo(res); /* No longer needed */ |
| | | return rv; |
| | | } |
| | | |
| | | |
| | | int cp_sock_accept(CP_SOCK *serv_sock, CP_SOCK *new_sock) |
| | | { |
| | | struct sockaddr_in saddr; |
| | | socklen_t len = sizeof(saddr); |
| | | int fd = -1; |
| | | int rv = 0; |
| | | |
| | | if(!serv_sock || !new_sock || serv_sock->fd<0 ) |
| | | { |
| | | log_err("Invalide input arguments\n"); |
| | | rv = -1; |
| | | goto cleanup; |
| | | } |
| | | |
| | | log_dbg("accept new client from server [fd=%d %s:%d] now\n", serv_sock->fd, serv_sock->laddr, serv_sock->lport); |
| | | |
| | | if( (fd=accept(serv_sock->fd, (struct sockaddr *)&saddr, &len)) < 0 ) |
| | | { |
| | | log_err("Accept new client from server [fd=%d %s:%d] failed: %s\n", |
| | | serv_sock->fd, serv_sock->laddr, serv_sock->lport, strerror(errno)); |
| | | rv = -2; |
| | | goto cleanup; |
| | | } |
| | | |
| | | /* Set socket buffer size */ |
| | | cp_sock_set_buffer(fd, new_sock->rsize, new_sock->ssize); |
| | | /* Enable socket keepalive to detect network */ |
| | | cp_sock_set_keepalive(fd, new_sock->keepintvl, new_sock->keepcnt); |
| | | cp_sock_set_nonblock(fd); |
| | | |
| | | new_sock->fd = fd; |
| | | new_sock->mode = CP_SOCK_MODE_ACCEPT; |
| | | /* get remote address */ |
| | | strncpy (new_sock->raddr, inet_ntoa(saddr.sin_addr), sizeof(new_sock->raddr)-1); |
| | | new_sock->rport = ntohs(saddr.sin_port); |
| | | |
| | | /* Get local address */ |
| | | len = sizeof(saddr); |
| | | if (getsockname (new_sock->fd, (struct sockaddr *) &saddr, (socklen_t *) &len)) |
| | | { |
| | | strncpy(new_sock->laddr, serv_sock->laddr, sizeof(new_sock->laddr)-1); |
| | | new_sock->lport = serv_sock->lport; |
| | | } |
| | | else |
| | | { |
| | | strncpy (new_sock->laddr, inet_ntoa (saddr.sin_addr), sizeof (new_sock->laddr) - 1); |
| | | new_sock->lport = ntohs (saddr.sin_port); |
| | | } |
| | | |
| | | cleanup: |
| | | if(!rv) |
| | | { |
| | | new_sock->status = SOCK_STAT_ACCEPTED; |
| | | new_sock->actv_time = time_now(); |
| | | log_nrml("Accept new client socket [%d %s:%d] <== [%s:%d]\n", |
| | | new_sock->fd, new_sock->laddr, new_sock->lport, new_sock->raddr, new_sock->rport); |
| | | } |
| | | else |
| | | { |
| | | log_err("Accept new client from server [%d] on [%s:%d] failed\n", |
| | | serv_sock->fd, serv_sock->raddr, serv_sock->rport); |
| | | close(fd); |
| | | } |
| | | |
| | | return rv; |
| | | } |
| | | |
| | | |
| | | /* |
| | | * Description: Create a socket connect to the remove server |
| | | * Input args: $sock: The socket contex $raddr: Remote server address |
| | | * $rport: Remote server listened port |
| | | * $lport: Use this local port connect to remote server |
| | | * Output args: None |
| | | * Return value: <0:connect failed ==0:connect ok >0:connect in progress |
| | | * |
| | | */ |
| | | int cp_sock_connect(CP_SOCK *sock, char *raddr, int rport, int lport) |
| | | { |
| | | int rv = 0; |
| | | int fd = -1; |
| | | char service[20]; |
| | | struct addrinfo hints, *rp; |
| | | struct addrinfo *res = NULL; |
| | | struct in_addr inaddr; |
| | | struct sockaddr_in saddr; |
| | | int len = sizeof(saddr); |
| | | |
| | | if(!sock || !(sock->flag&FLAG_SOCK_INIT) || !raddr || rport<=0) |
| | | { |
| | | log_err("Invalide input arguments\n"); |
| | | rv = -1; |
| | | goto failed; |
| | | } |
| | | |
| | | if(SOCK_STAT_CONNECTED == sock->status) |
| | | { |
| | | return 0; |
| | | } |
| | | else if(SOCK_STAT_CONNECTING == sock->status) |
| | | { |
| | | goto connecting; |
| | | } |
| | | |
| | | log_dbg("create socket connect to remote server [%s:%d] now\n", raddr, rport); |
| | | |
| | | memset(&hints, 0, sizeof(struct addrinfo)); |
| | | hints.ai_family = AF_INET; /* Only support IPv4 */ |
| | | hints.ai_socktype = SOCK_STREAM; |
| | | hints.ai_protocol = IPPROTO_TCP; /* TCP protocol */ |
| | | hints.ai_flags = AI_PASSIVE; |
| | | |
| | | /* If 'raddr' is a valid IP address, then don't use name resolution */ |
| | | if(raddr && inet_aton(raddr, &inaddr)) |
| | | { |
| | | log_info("%s is a valid IP address, don't use name resolution.\n", raddr); |
| | | hints.ai_flags |= AI_NUMERICHOST; |
| | | } |
| | | |
| | | /* Obtain address(es) matching host/port */ |
| | | snprintf(service, sizeof(service), "%d", rport); |
| | | if( (rv=getaddrinfo(raddr, service, &hints, &res)) ) |
| | | { |
| | | log_err("getaddrinfo() parser [%s:%s] failed: %s\n", raddr, service, gai_strerror(rv)); |
| | | rv = -2; |
| | | goto failed; |
| | | } |
| | | |
| | | cp_sock_close(sock); /* close any opened socket on it */ |
| | | sock->fd = -1; |
| | | |
| | | /* getaddrinfo() returns a list of address structures. Try each |
| | | * address until we successfully connect or bind*/ |
| | | for (rp=res; rp!=NULL; rp=rp->ai_next) |
| | | { |
| | | fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); |
| | | |
| | | /* Create the socket */ |
| | | if( fd < 0) |
| | | { |
| | | log_err("socket() create failed: %s\n", strerror(errno)); |
| | | rv = -3; |
| | | continue; |
| | | } |
| | | log_trace("create socket[%p:%d] with connect mode ok\n", sock, fd); |
| | | |
| | | /* We need bind lport to this socket */ |
| | | if(lport > 0) |
| | | { |
| | | memset(&saddr, 0, len); |
| | | saddr.sin_family = AF_INET; |
| | | saddr.sin_port = htons ((u_short) lport); |
| | | |
| | | if ( bind(fd, (struct sockaddr *)&saddr, len) ) |
| | | { |
| | | rv = -4; |
| | | close(fd); |
| | | log_err("Bind port[%d] to connect socket [%d] failed: %s\n", lport, fd, strerror(errno)); |
| | | continue; |
| | | } |
| | | else |
| | | { |
| | | sock->lport = lport; |
| | | rv = 0; |
| | | log_dbg("Bind port[%d] to connect socket [%d] OK\n", lport, fd); |
| | | } |
| | | } |
| | | |
| | | /* Set socket options */ |
| | | cp_sock_set_buffer(fd, sock->rsize, sock->ssize); |
| | | cp_sock_set_keepalive(fd, sock->keepintvl, sock->keepcnt); |
| | | cp_sock_set_nonblock(fd); |
| | | |
| | | /* Nono block Connect to the remote server */ |
| | | if(0==connect(fd, rp->ai_addr, rp->ai_addrlen)) |
| | | { |
| | | /* Conenct to server successfully */ |
| | | sock->fd = fd; |
| | | sock->status = SOCK_STAT_CONNECTING; |
| | | |
| | | memcpy(&sock->saddr, &rp->ai_addr, sizeof(sock->saddr)); |
| | | |
| | | rv = 0; |
| | | goto connected; |
| | | } |
| | | else |
| | | { |
| | | if(EINPROGRESS == errno) |
| | | { |
| | | /* Connect to server now in progress */ |
| | | sock->fd = fd; |
| | | sock->status = SOCK_STAT_CONNECTING; |
| | | memcpy(&sock->saddr, &rp->ai_addr, sizeof(sock->saddr)); |
| | | |
| | | rv = 0; |
| | | goto connecting; |
| | | } |
| | | else |
| | | { |
| | | /* Connect to server failed. */ |
| | | close(fd); |
| | | rv = -5; |
| | | log_err("connect() to server failed: %s\n", strerror(errno)); |
| | | goto failed; |
| | | } |
| | | } |
| | | |
| | | close(fd); |
| | | } /* for (rp=res; rp!=NULL; rp=rp->ai_next) */ |
| | | |
| | | |
| | | if(sock->fd < 0) |
| | | { |
| | | close(fd); |
| | | goto failed; |
| | | } |
| | | |
| | | |
| | | connecting: |
| | | if(SOCK_STAT_CONNECTING == sock->status) |
| | | { |
| | | |
| | | len = sizeof(sock->saddr); |
| | | |
| | | errno = 0; |
| | | if( !connect(sock->fd, &sock->saddr, len) ) |
| | | { |
| | | /* connect() return 0 means it already connected */ |
| | | sock->status = SOCK_STAT_CONNECTED; |
| | | rv = 0; |
| | | goto connected; |
| | | } |
| | | |
| | | /* Connect failure will continue to check */ |
| | | switch (errno) |
| | | { |
| | | case EISCONN: |
| | | sock->status = SOCK_STAT_CONNECTED; |
| | | rv = 0; |
| | | goto connected; |
| | | |
| | | case EALREADY: |
| | | case EINPROGRESS: |
| | | log_dbg("socket[%d] connect to remote [%s:%d] in progress\n", sock->fd, raddr, rport); |
| | | rv = 0; |
| | | goto cleanup; |
| | | |
| | | default: |
| | | log_err("socket[%d] connect to remote [%s:%d] failed: %s\n", sock->fd, raddr, rport, strerror(errno)); |
| | | sock->status = SOCK_STAT_DISCONNECT; |
| | | rv = -7; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | connected: |
| | | if(SOCK_STAT_CONNECTED == sock->status) |
| | | { |
| | | rv = 0; |
| | | |
| | | log_nrml("socket[%d] connected to remote server [%s:%d]\n", sock->fd, raddr, rport); |
| | | /* Set remote address */ |
| | | sock->rport=rport; |
| | | strncpy (sock->raddr, raddr, sizeof(sock->raddr)-1); |
| | | sock->actv_time = time_now(); |
| | | |
| | | /* Get local address */ |
| | | memset(&saddr, 0, len); |
| | | len = sizeof(saddr); |
| | | |
| | | if (!getsockname (sock->fd, (struct sockaddr *) &saddr, (socklen_t *) &len)) |
| | | { |
| | | strncpy (sock->laddr, inet_ntoa (saddr.sin_addr), sizeof (sock->laddr) - 1); |
| | | sock->lport = ntohs (saddr.sin_port); |
| | | } |
| | | else |
| | | { |
| | | memset(&sock->laddr, 0, sizeof(sock->laddr)); |
| | | sock->lport = lport; |
| | | } |
| | | goto cleanup; |
| | | } |
| | | |
| | | |
| | | failed: |
| | | log_err("Create socket connect to [%s:%d] failed\n", raddr, rport); |
| | | if(sock && sock->fd >= 0) |
| | | close(sock->fd); |
| | | |
| | | cleanup: |
| | | if(res) |
| | | freeaddrinfo(res); /* No longer needed */ |
| | | |
| | | return rv; |
| | | } |
| | | |
| | | |
| | | int cp_sock_recv(CP_SOCK *sock) |
| | | { |
| | | int rv, left; |
| | | int flag; |
| | | cp_string *rbuf; |
| | | |
| | | if(!sock || !sock->rbuf || !sock->rbuf->data || sock->fd<0) |
| | | { |
| | | log_err("Invalide input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | rbuf = sock->rbuf; |
| | | left = rbuf->size-rbuf->len; |
| | | flag = left ? 0 : MSG_PEEK; |
| | | |
| | | if(left <= 0) |
| | | return 0; |
| | | |
| | | rv=recv(sock->fd, &rbuf->data[rbuf->len], left, flag); |
| | | if( rv > 0) |
| | | { |
| | | rbuf->len += rv; |
| | | } |
| | | else if(rv<0) |
| | | { |
| | | if(EAGAIN==errno || EINPROGRESS==errno) |
| | | { |
| | | log_warn("socket [%d] please recv data again: %s\n", sock->fd, strerror(errno)); |
| | | rv = 0; |
| | | } |
| | | else |
| | | { |
| | | log_err("socket [%d] recv data failed: %s\n", sock->fd, strerror(errno)); |
| | | rv = -2; |
| | | } |
| | | } |
| | | |
| | | if(rv > 0) |
| | | { |
| | | sock->actv_time = sock->msg_time = time_now(); |
| | | } |
| | | return rv; |
| | | } |
| | | |
| | | int cp_sock_send(CP_SOCK *sock) |
| | | { |
| | | int rv; |
| | | struct pollfd sock_poll; |
| | | |
| | | if(!sock || sock->fd<0 || !sock->sbuf->data || sock->sbuf->len<=0) |
| | | { |
| | | log_err("Invalide input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | sock_poll.events = POLLOUT; |
| | | sock_poll.fd = sock->fd; |
| | | |
| | | if( (rv=poll(&sock_poll, 1, 0)) > 0 ) |
| | | { |
| | | if( !(POLLOUT &sock_poll.events) ) |
| | | { |
| | | return -2; |
| | | } |
| | | |
| | | if ( (rv=send(sock->fd, sock->sbuf->data, sock->sbuf->len, MSG_NOSIGNAL)) < 0) |
| | | { |
| | | if (EAGAIN == errno) |
| | | { |
| | | log_warn("socket [%d] please send data again: %s\n", sock->fd, strerror(errno)); |
| | | return 0; |
| | | } |
| | | else |
| | | { |
| | | log_err("socket [%d] send data failed: %s\n", sock->fd, strerror(errno)); |
| | | return -4; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | sock->sbuf->len -= rv; |
| | | sock->actv_time = time_now(); |
| | | memmove (sock->sbuf->data, sock->sbuf->data+rv, sock->sbuf->len); |
| | | return rv; |
| | | } |
| | | } |
| | | else /* poll()<0 means failed, poll()==0 means timeout */ |
| | | { |
| | | log_err("send data from socket [%d] poll failed: %s\n", sock->fd, strerror(errno)); |
| | | return 0; |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int cp_sock_set_nonblock(int sockfd) |
| | | { |
| | | int opts; |
| | | /* |
| | | * fcntl may set: |
| | | * |
| | | * EACCES, EAGAIN: Operation is prohibited by locks held by other |
| | | * processes. Or, operation is prohibited because the file has |
| | | * been memory-mapped by another process. |
| | | * EBADF: fd is not an open file descriptor, or the command was F_SETLK |
| | | * or F_SETLKW and the file descriptor open mode doesn't match |
| | | * with the type of lock requested. |
| | | * EDEADLK: It was detected that the specified F_SETLKW command would |
| | | * cause a deadlock. |
| | | * EFAULT: lock is outside your accessible address space. |
| | | * EINTR: For F_SETLKW, the command was interrupted by a signal. For |
| | | * F_GETLK and F_SETLK, the command was interrupted by a signal |
| | | * before the lock was checked or acquired. Most likely when |
| | | * locking a remote file (e.g. locking over NFS), but can |
| | | * sometimes happen locally. |
| | | * EINVAL: For F_DUPFD, arg is negative or is greater than the maximum |
| | | * allowable value. For F_SETSIG, arg is not an allowable signal |
| | | * number. |
| | | * EMFILE: For F_DUPFD, the process already has the maximum number of |
| | | * file descriptors open. |
| | | * ENOLCK: Too many segment locks open, lock table is full, or a remote |
| | | * locking protocol failed (e.g. locking over NFS). |
| | | * EPERM: Attempted to clear the O_APPEND flag on a file that has the |
| | | * append-only attribute set. |
| | | */ |
| | | opts = fcntl(sockfd, F_GETFL); |
| | | if (opts < 0) |
| | | { |
| | | log_warn("fcntl() get socket options failure: %s\n", strerror(errno)); |
| | | return -1; |
| | | } |
| | | |
| | | opts |= O_NONBLOCK; |
| | | |
| | | if (fcntl(sockfd, F_SETFL, opts) < 0) |
| | | { |
| | | log_warn("fcntl() set socket options failure: %s\n", strerror(errno)); |
| | | return -1; |
| | | } |
| | | |
| | | log_dbg("Set socket[%d] none blocking\n", sockfd); |
| | | return opts; |
| | | } |
| | | |
| | | int cp_sock_set_buffer(int sockfd, int rsize, int ssize) |
| | | { |
| | | int opt; |
| | | socklen_t optlen = sizeof(opt); |
| | | |
| | | if(sockfd < 0) |
| | | return -1; |
| | | |
| | | /* Get system default receive buffer size, Linux X86: 85K */ |
| | | if (getsockopt (sockfd, SOL_SOCKET, SO_RCVBUF, (char *) &opt, &optlen)) |
| | | { |
| | | log_warn("getsockopt() get receive buffer failure: %s\n", strerror(errno)); |
| | | return -2; |
| | | } |
| | | |
| | | /* Only when current receive buffer size larger than the default one will change it */ |
| | | if(rsize > opt) |
| | | { |
| | | opt = (int) rsize; |
| | | if (setsockopt (sockfd, SOL_SOCKET, SO_RCVBUF, (char *) &opt, optlen)) |
| | | { |
| | | log_warn("setsockopt() set receive buffer to %d failure: %s\n", opt, strerror(errno)); |
| | | return -2; |
| | | } |
| | | } |
| | | |
| | | /* Get system default send buffer size, Linux X86: 16K */ |
| | | if (getsockopt (sockfd, SOL_SOCKET, SO_SNDBUF, (char *) &opt, &optlen)) |
| | | { |
| | | log_warn("getsockopt() get send buffer failure: %s\n", strerror(errno)); |
| | | return -3; |
| | | } |
| | | |
| | | /* Only when current receive buffer size larger than the default one will change it */ |
| | | if(ssize > opt) |
| | | { |
| | | opt = (int) ssize; |
| | | if (setsockopt (sockfd, SOL_SOCKET, SO_SNDBUF, (char *) &opt, optlen)) |
| | | { |
| | | log_warn("setsockopt() set send buffer to %d failure: %s\n", opt, strerror(errno)); |
| | | return -3; |
| | | } |
| | | } |
| | | |
| | | log_info("Set socket[%d] RCVBUF size:%d SNDBUF size:%d\n", sockfd, rsize, ssize); |
| | | return 0; |
| | | } |
| | | |
| | | int cp_sock_set_reuseaddr(int sockfd) |
| | | { |
| | | int opt = 1; |
| | | int len = sizeof (int); |
| | | |
| | | if (setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, (void *) &opt, len)) |
| | | { |
| | | log_err("Set socket[%d] option SO_REUSEADDR failed:%s\n", sockfd, strerror(errno)); |
| | | return -1; |
| | | } |
| | | log_dbg("Set socket[%d] option SO_REUSEADDR ok\n", sockfd); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | /* |
| | | * Enable socket SO_KEEPALIVE, if the connection disconnected, any system call on socket |
| | | * will return immediately and errno will be set to "WSAENOTCONN" |
| | | * |
| | | * keepalive is not program related, but socket related, * so if you have multiple sockets, |
| | | * you can handle keepalive for each of them separately. |
| | | * |
| | | * Reference: http://tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/ |
| | | */ |
| | | int cp_sock_set_keepalive(int sockfd, int keepintvl, int keepcnt) |
| | | { |
| | | int opt; |
| | | |
| | | if(sockfd < 0) |
| | | return -1; |
| | | |
| | | /* Enable the KEEPALIVE flag */ |
| | | opt = 1; |
| | | if (setsockopt (sockfd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof (opt))) |
| | | { |
| | | log_warn("setsockopt() enable SO_KEEPALIVE failure: %s\n", strerror(errno)); |
| | | return -2; |
| | | } |
| | | |
| | | if(keepintvl || keepcnt) |
| | | { |
| | | /* |
| | | * The tcp_keepidle parameter specifies the interval between the last data packet sent |
| | | * (simple ACKs are not considered data) and the first keepalive probe; after the |
| | | * connection is marked to need keepalive, this counter is not used any further. |
| | | * ~ >: cat /proc/sys/net/ipv4/tcp_keepalive_time |
| | | * 7200 |
| | | */ |
| | | opt = 3; /* 3 seconds */ |
| | | if (setsockopt (sockfd, SOL_TCP, TCP_KEEPIDLE, (char *) &opt, sizeof (opt))) |
| | | { |
| | | log_err("setsockopt() set TCP_KEEPIDLE to %d seconds failure: %s\n", opt, strerror(errno)); |
| | | return -3; |
| | | } |
| | | |
| | | if((opt=keepintvl) > 0) |
| | | { |
| | | /* |
| | | * The tcp_keepintvl parameter specifies the interval between subsequential keepalive |
| | | * probes, regardless of what the connection has exchanged in the meantime. |
| | | * ~ >: cat /proc/sys/net/ipv4/tcp_keepalive_intvl |
| | | * 75 |
| | | */ |
| | | if (setsockopt (sockfd, SOL_TCP, TCP_KEEPINTVL, (char *) &opt, sizeof (opt))) |
| | | { |
| | | log_err("setsockopt() set TCP_KEEPINTVL to %d failure: %s\n", opt, strerror(errno)); |
| | | return -4; |
| | | } |
| | | } |
| | | |
| | | if((opt=keepcnt) > 0) |
| | | { |
| | | /* |
| | | * The TCP_KEEPCNT option specifies the maximum number of unacknowledged probes to |
| | | * send before considering the connection dead and notifying the application layer |
| | | * probes to be sent. The value of TCP_KEEPCNT is an integer value between 1 and n, |
| | | * where n is the value of the systemwide tcp_keepcnt parameter. |
| | | * ~ >: cat /proc/sys/net/ipv4/tcp_keepalive_probes |
| | | * 9 |
| | | */ |
| | | if (setsockopt (sockfd, SOL_TCP, TCP_KEEPCNT, (char *) &opt, sizeof (opt))) |
| | | { |
| | | log_err("setsockopt() set TCP_KEEPCNT to %d failure: %s\n", opt, strerror(errno)); |
| | | return -5; |
| | | } |
| | | } |
| | | } |
| | | |
| | | log_dbg("Set socket[%d] KEEPINTVL:%d KEEPCNT:%d\n", sockfd, keepintvl, keepcnt); |
| | | return 0; |
| | | } |
| | | |
| | | |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_sock.h |
| | | * Description: This head file |
| | | * |
| | | * Version: 1.0.0(10/26/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "10/26/2012 01:21:38 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | #ifndef __CP_SOCK_H |
| | | #define __CP_SOCK_H |
| | | |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <netdb.h> |
| | | #include <fcntl.h> |
| | | #include <unistd.h> |
| | | #include <sys/un.h> |
| | | #include <poll.h> |
| | | #include <errno.h> |
| | | |
| | | #include <sys/types.h> |
| | | #include <sys/socket.h> |
| | | #include <linux/sockios.h> |
| | | #include <sys/ioctl.h> |
| | | #include <sys/socket.h> |
| | | #include <netinet/in.h> |
| | | #include <netinet/tcp.h> |
| | | #include <arpa/inet.h> |
| | | |
| | | #include "cp_klist.h" |
| | | #include "cp_string.h" |
| | | #include "cp_fds.h" |
| | | |
| | | |
| | | #define CP_DEF_RCVBUF_SIZE 2048 |
| | | #define CP_DEF_SNDBUF_SIZE 2048 |
| | | |
| | | #define CP_SOCK_RCVBUF 2048 |
| | | #define CP_SOCK_SNDBUF 2048 |
| | | |
| | | #define CP_SOCK_DEF_IDLE_TIMEOUT 120*1000 /* 2 minutes */ |
| | | #define CP_SOCK_DEF_MSG_TIMEOUT 120*1000 /* 2 minutes */ |
| | | |
| | | #define CP_SOCK_KEEPINTVL 600 |
| | | #define CP_SOCK_KEEPCNT 3 |
| | | |
| | | #define CP_SOCK_MODE_NONE 0 |
| | | #define CP_SOCK_MODE_ACCEPT 1 |
| | | #define CP_SOCK_MODE_CONNECT 2 |
| | | #define CP_SOCK_MODE_LISTEN 3 |
| | | |
| | | enum |
| | | { |
| | | CP_SOCK_EVENT_READ = EPOLLIN, /* compatilbe with EPOLLIN */ |
| | | CP_SOCK_EVENT_WRITE = EPOLLOUT, /* compatilbe with EPOLLOUT */ |
| | | CP_SOCK_EVENT_ERROR = EPOLLERR, /* compatilbe with EPOLLERR */ |
| | | CP_SOCK_EVENT_HUP = EPOLLHUP, /* compatilbe with EPOLLHUP */ |
| | | CP_SOCK_EVENT_IDLE_TIMEOUT = (1<<16), /* compatilbe with EPOLL reserved*/ |
| | | CP_SOCK_EVENT_MSG_TIMEOUT = (1<<17), /* compatible with EPOLL reserved*/ |
| | | }; |
| | | |
| | | struct _CP_SOCK; |
| | | struct _CP_FDS; |
| | | |
| | | typedef void (*PRIVT_FREE)(void); |
| | | typedef int (*CP_SOCK_EVENT_CALLBACK)(struct _CP_SOCK *sock); |
| | | typedef struct _CP_SOCK_CALLBACK |
| | | { |
| | | CP_SOCK_EVENT_CALLBACK error; |
| | | CP_SOCK_EVENT_CALLBACK read; |
| | | CP_SOCK_EVENT_CALLBACK write; |
| | | } CP_SOCK_CALLBACK; |
| | | |
| | | |
| | | #define FLAG_SOCK_INIT (1<<0) |
| | | #define FLAG_SOCK_MALLOC (1<<1) |
| | | #define FLAG_SOCK_EPOLLED (1<<2) |
| | | #define FLAG_SOCK_REGISTRY (1<<3) |
| | | #define FLAG_SOCK_INQUEUE (1<<4) |
| | | #define FLAG_SOCK_TASKED (1<<5) |
| | | |
| | | #define SOCK_STAT_INIT 0 |
| | | #define SOCK_STAT_CONNECTING 1 |
| | | #define SOCK_STAT_CONNECTED 2 |
| | | #define SOCK_STAT_LISTENED 2 |
| | | #define SOCK_STAT_ACCEPTED 2 |
| | | #define SOCK_STAT_ALREADY 2 |
| | | #define SOCK_STAT_DISCONNECT 3 |
| | | |
| | | typedef struct _CP_SOCK |
| | | { |
| | | int fd; /* the socket file description */ |
| | | int mode; /* socket work mode: listen, accept, connect */ |
| | | unsigned short flag; /* Refer to the follow definition */ |
| | | unsigned char status; /* current socket status */ |
| | | |
| | | unsigned long actv_time; /* The last time get event(send/recv) data in this socket */ |
| | | unsigned long msg_time; /* The last time get incoming data in this socket */ |
| | | unsigned long idle_timeout; /* this is set to the socket idle timeout value, when timeout will disconnect */ |
| | | unsigned long msg_timeout; /* this is set to the socket recv data timeout value, */ |
| | | |
| | | int keepintvl; /* heartbeat(keepalive) detect interval */ |
| | | int keepcnt; /* heartbeat(keepalive) count */ |
| | | int rsize; /* ioctl() set socket recv buffer size */ |
| | | int ssize; /* ioctl() set socket send buffer size */ |
| | | |
| | | struct epoll_event event; /* epoll_wait returned event */ |
| | | |
| | | cp_string *sbuf; /* send buffer */ |
| | | cp_string *rbuf; /* receive buffer */ |
| | | |
| | | struct sockaddr saddr; /* sockaddr for connect */ |
| | | char laddr[16]; /* local IP address*/ |
| | | int lport; /* local port */ |
| | | char raddr[16]; /* remote IP address */ |
| | | int rport; /* remote port */ |
| | | |
| | | struct _CP_FDS *fds; /* epoll fds contex */ |
| | | CP_SOCK_EVENT_CALLBACK cbfunc; /* event callback function */ |
| | | CP_SOCK_EVENT_CALLBACK client_func; /* client data callback function, only server socket use it */ |
| | | struct _CP_SOCK *serv_sock; /* Accept socket used to point to the server socket */ |
| | | |
| | | int max_client; /* max clients, only listen socket use it*/ |
| | | int accept_cnt; /* current clients number, only listen socket use it*/ |
| | | struct list_head accept_list; /* all the accept client list head, only listen socket use it */ |
| | | |
| | | void *privt; /* socket private data */ |
| | | PRIVT_FREE privt_free; /* private data free function if it's malloc */ |
| | | |
| | | int index; /* The index member position in the task array */ |
| | | struct list_head rlist; /* The list_head member position just for the registry list */ |
| | | |
| | | /* flag definitions |
| | | * 1 1 1 1 1 1 1 1 |
| | | * | | | | | | | |______ Initial flag - 0: no 1: yes |
| | | * | | | | | | |________ Malloc flag - 0: variable, 1: malloc |
| | | * | | | | | |__________ registry flag - 0: not in, 1: in the registry list |
| | | * | | | | |____________ epolled flag - 0: not in, 1: put in epoll |
| | | * | | | |______________ in queue flag - 0: not in, 1: put in queue |
| | | * | | |________________ task flag - 0: not in, 1: in the task list |
| | | * | |__________________ reserved |
| | | * |____________________ reserved |
| | | */ |
| | | } CP_SOCK; |
| | | |
| | | |
| | | static void inline cp_sock_set_idle_timeout(CP_SOCK *sock, unsigned long timeout) |
| | | { |
| | | sock->idle_timeout = timeout; |
| | | } |
| | | |
| | | static void inline cp_sock_set_msg_timeout(CP_SOCK *sock, unsigned long timeout) |
| | | { |
| | | sock->msg_timeout = timeout; |
| | | } |
| | | |
| | | static void inline cp_sock_set_private_data(CP_SOCK *sock, void *data, PRIVT_FREE free) |
| | | { |
| | | sock->privt = data; |
| | | sock->privt_free = free; |
| | | } |
| | | |
| | | extern CP_SOCK *cp_sock_init(CP_SOCK *sock, unsigned int rsize, unsigned int ssize, int keepintvl, int keepcnt); |
| | | extern int cp_sock_close(CP_SOCK *sock); |
| | | extern void cp_sock_term(CP_SOCK *sock); |
| | | #define cp_sock_term_clear(sock) {cp_sock_term(sock); sock=NULL;} |
| | | |
| | | extern int cp_sock_listen(CP_SOCK *sock, char *laddr, int lport, int backlog); |
| | | extern int cp_sock_connect(CP_SOCK *sock, char *raddr, int rport, int lport); |
| | | extern int cp_sock_accept(CP_SOCK *serv_sock, CP_SOCK *new_sock); |
| | | |
| | | extern int cp_sock_recv(CP_SOCK *sock); |
| | | extern int cp_sock_send(CP_SOCK *sock); |
| | | |
| | | extern int cp_sock_set_reuseaddr(int sockfd); |
| | | extern int cp_sock_set_keepalive(int sockfd, int keepintvl, int keepcnt); |
| | | extern int cp_sock_set_nonblock(int sockfd); |
| | | extern int cp_sock_set_buffer(int sockfd, int rsize, int ssize); |
| | | |
| | | #endif /* __CP_SOCK_H */ |
New file |
| | |
| | | |
| | | /** |
| | | * @addtogroup cp_string |
| | | */ |
| | | /** @{ */ |
| | | /** |
| | | * @file |
| | | * cp_string - 'safe' string implementation |
| | | */ |
| | | |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <string.h> |
| | | #include <unistd.h> |
| | | #include <errno.h> |
| | | |
| | | #include "cp_string.h" |
| | | #include "cp_common.h" |
| | | |
| | | cp_string *cp_string_create(char *data, int len) |
| | | { |
| | | cp_string *str; |
| | | |
| | | #ifdef DEBUG |
| | | if (len < 0) |
| | | { |
| | | return NULL; |
| | | } |
| | | #endif |
| | | |
| | | str = t_malloc(sizeof(cp_string)); |
| | | |
| | | if (str) |
| | | { |
| | | str->len = len; |
| | | str->size = str->len + 1; |
| | | str->data = t_malloc(str->size * sizeof(char)); |
| | | if (str->data) |
| | | memcpy(str->data, data, str->len); |
| | | else |
| | | { |
| | | t_free(str); |
| | | str = NULL; |
| | | } |
| | | } |
| | | |
| | | return str; |
| | | } |
| | | |
| | | cp_string *cp_string_create_empty(int initial_size) |
| | | { |
| | | cp_string *str = t_malloc(sizeof(cp_string)); |
| | | |
| | | if (str) |
| | | { |
| | | str->len = 0; |
| | | str->size = initial_size; |
| | | str->data = (char *) t_malloc(str->size * sizeof(char)); |
| | | if (str->data == NULL) |
| | | { |
| | | t_free(str); |
| | | str = NULL; |
| | | } |
| | | } |
| | | |
| | | return str; |
| | | } |
| | | |
| | | void cp_string_destroy(cp_string *str) |
| | | { |
| | | if (str) |
| | | { |
| | | if (str->data) |
| | | { |
| | | t_free(str->data); |
| | | } |
| | | |
| | | t_free(str); |
| | | } |
| | | } |
| | | |
| | | |
| | | void cp_string_clear_data(cp_string *str) |
| | | { |
| | | if (str && str->data) |
| | | { |
| | | memset(str->data, 0, str->size); |
| | | str->len = 0; |
| | | } |
| | | } |
| | | |
| | | cp_string *cp_string_cstrcpy(cp_string *str, char *cstr) |
| | | { |
| | | if (str) |
| | | { |
| | | str->len = strlen(cstr); |
| | | if (str->size < str->len + 1) |
| | | { |
| | | str->size = str->len + 1; |
| | | str->data = t_malloc(str->size * sizeof(char)); |
| | | } |
| | | if (str->data) |
| | | memcpy(str->data, cstr, str->size * sizeof(char)); |
| | | else |
| | | { |
| | | t_free(str); |
| | | str = NULL; |
| | | } |
| | | } |
| | | |
| | | return str; |
| | | } |
| | | |
| | | int cp_string_copy(cp_string *dst, cp_string *src) |
| | | { |
| | | int left; |
| | | int size; |
| | | |
| | | if(!dst || !dst->data || !src || !src->data) |
| | | return 0; |
| | | |
| | | left=dst->size - dst->len; |
| | | size = left>src->len ? src->len : left; |
| | | |
| | | memcpy(&dst->data[dst->len], src->data, size); |
| | | dst->len += size; |
| | | |
| | | return size; |
| | | } |
| | | |
| | | int cp_string_cstrcopy(cp_string *dst, char *string, int len) |
| | | { |
| | | int left; |
| | | int size; |
| | | |
| | | if(!dst || !dst->data || !string || len<=0) |
| | | return 0; |
| | | |
| | | left=dst->size - dst->len; |
| | | size = left>len ? len : left; |
| | | |
| | | memcpy(&dst->data[dst->len], string, size); |
| | | dst->len += size; |
| | | |
| | | return size; |
| | | } |
| | | |
| | | |
| | | int cp_string_move(cp_string *dst, cp_string *src) |
| | | { |
| | | int left; |
| | | int size; |
| | | |
| | | if(!dst || !dst->data || !src || !src->data) |
| | | return 0; |
| | | |
| | | /* Check how many left size in $dst and set the size */ |
| | | left=dst->size - dst->len; |
| | | size = left>src->len ? src->len : left; |
| | | |
| | | /* copy the $src data to $dst */ |
| | | memcpy(&dst->data[dst->len], src->data, size); |
| | | dst->len += size; |
| | | |
| | | /* remove the $src copied data in it*/ |
| | | src->len -= size; |
| | | memmove (src->data, src->data+size, src->len); |
| | | |
| | | return size; |
| | | } |
| | | |
| | | cp_string *cp_string_dup(cp_string *src) |
| | | { |
| | | cp_string *str = t_malloc(sizeof(cp_string)); |
| | | |
| | | if (str) |
| | | { |
| | | *str = *src; /* bitwise copy */ |
| | | str->data = t_malloc((str->len + 1) * sizeof(char)); |
| | | if (str->data) |
| | | memcpy(str->data, src->data, (str->len + 1) * sizeof(char)); |
| | | else |
| | | { |
| | | t_free(str); |
| | | str = NULL; |
| | | } |
| | | } |
| | | |
| | | return str; |
| | | } |
| | | |
| | | cp_string *cp_string_cstrdup(char *src) |
| | | { |
| | | cp_string *str = t_malloc(sizeof(cp_string)); |
| | | |
| | | if (str) |
| | | { |
| | | str->len = strlen(src); |
| | | str->size = str->len + 1; |
| | | str->data = t_malloc(str->size * sizeof(char)); |
| | | if (str->data == NULL) |
| | | { |
| | | t_free(str); |
| | | return NULL; |
| | | } |
| | | memcpy(str->data, src, str->size); |
| | | } |
| | | |
| | | return str; |
| | | } |
| | | |
| | | cp_string *cp_string_cat(cp_string *str, cp_string *appendum) |
| | | { |
| | | int len = str->len; |
| | | str->len += appendum->len; |
| | | if (str->len + 1 > str->size) |
| | | { |
| | | str->size = str->len + 1; |
| | | str->data = realloc(str->data, str->size * sizeof(char)); |
| | | } |
| | | if (str->data) |
| | | memcpy(str->data + len * sizeof(char), appendum->data, |
| | | appendum->len * sizeof(char)); |
| | | |
| | | return str; |
| | | } |
| | | |
| | | cp_string *cp_string_cstrcat(cp_string *str, char *cstr) |
| | | { |
| | | int len = str->len; |
| | | int clen = strlen(cstr); |
| | | |
| | | str->len += clen * sizeof(char); |
| | | if (str->len + 1 > str->size) |
| | | { |
| | | // str->size = str->len + 0x400 - (str->len % 0x400); /* align to 1kb block */ |
| | | str->size = str->len + 1; |
| | | str->data = realloc(str->data, str->size * sizeof(char)); |
| | | } |
| | | if (str->data) |
| | | memcpy(str->data + len * sizeof(char), cstr, clen); |
| | | |
| | | return str; |
| | | } |
| | | |
| | | cp_string *cp_string_append_char(cp_string *str, char ch) |
| | | { |
| | | if (str->len + 1 > str->size) |
| | | { |
| | | str->size = str->len + 0x100; |
| | | str->data = realloc(str->data, str->size * sizeof(char)); |
| | | if (str->data == NULL) return NULL; |
| | | } |
| | | str->data[str->len++] = ch; |
| | | |
| | | return str; |
| | | } |
| | | |
| | | cp_string *cp_string_cat_bin(cp_string *str, void *bin, int len) |
| | | { |
| | | int olen = str->len; |
| | | str->len += len; |
| | | |
| | | if (str->len > str->size) |
| | | { |
| | | str->size = str->len + 0x400 - (str->len % 0x400); /* align to 1kb block */ |
| | | str->data = realloc(str->data, str->size * sizeof(char)); |
| | | } |
| | | memcpy(&str->data[olen], bin, len); |
| | | |
| | | return str; |
| | | } |
| | | |
| | | int cp_string_cmp(cp_string *s1, cp_string *s2) |
| | | { |
| | | if (s1 == s2) return 0; //~~ implies cp_string_cmp(NULL, NULL) == 0 |
| | | |
| | | if (s1 == NULL) return -1; |
| | | if (s2 == NULL) return 1; |
| | | |
| | | if (s1->len == s2->len) |
| | | return memcmp(s1->data, s2->data, s1->len); |
| | | else |
| | | { |
| | | int p = (s1->len > s2->len) ? s2->len : s1->len; |
| | | int rc = memcmp(s1->data, s2->data, p); |
| | | if (rc == 0) |
| | | return s1->len - s2->len; |
| | | return rc; |
| | | } |
| | | } |
| | | |
| | | char *cp_string_tocstr(cp_string *str) |
| | | { |
| | | char *cstr = NULL; |
| | | |
| | | if (str) |
| | | { |
| | | str->data[str->len * sizeof(char)] = '\0'; |
| | | // str->data[str->len * sizeof(char) + 1] = '\0'; |
| | | cstr = str->data; |
| | | } |
| | | |
| | | return cstr; |
| | | } |
| | | |
| | | int cp_string_len(cp_string *s) |
| | | { |
| | | return s->len; |
| | | } |
| | | |
| | | char *cp_string_data(cp_string *s) |
| | | { |
| | | return s->data; |
| | | } |
| | | |
| | | #define CHUNK 0x1000 |
| | | cp_string *cp_string_read(int fd, int len) |
| | | { |
| | | char buf[CHUNK]; |
| | | int read_len; |
| | | cp_string *res = NULL; |
| | | |
| | | if (len == 0) |
| | | read_len = CHUNK; |
| | | else |
| | | read_len = len < CHUNK ? len : CHUNK; |
| | | |
| | | while (len == 0 || res == NULL || res->len < len) |
| | | { |
| | | int rc = |
| | | read(fd, buf, read_len); |
| | | if (rc <= 0) break; |
| | | if (res == NULL) |
| | | { |
| | | res = cp_string_create(buf, rc); |
| | | if (res == NULL) return NULL; |
| | | } |
| | | else |
| | | cp_string_cat_bin(res, buf, rc); |
| | | } |
| | | |
| | | return res; |
| | | } |
| | | |
| | | int cp_string_write(cp_string *str, int fd) |
| | | { |
| | | int rc; |
| | | int total = 0; |
| | | |
| | | while (total < str->len) |
| | | { |
| | | rc = write(fd, &str->data[total], str->len - total); |
| | | |
| | | /* write sets EAGAIN when a socket is marked non-blocking and the |
| | | * write would block. trying to write again could result in spinning |
| | | * on the write call. |
| | | */ |
| | | if (rc == -1) |
| | | { |
| | | if (errno == EINTR /* || errno == EAGAIN */) /* try again */ |
| | | continue; |
| | | else |
| | | break; |
| | | } |
| | | total += rc; |
| | | } |
| | | |
| | | return total; |
| | | } |
| | | |
| | | cp_string *cp_string_read_file(char *filename) |
| | | { |
| | | cp_string *res; |
| | | FILE *fp = fopen(filename, "rb"); |
| | | if (fp == NULL) return NULL; |
| | | |
| | | res = cp_string_read(fileno(fp), 0); |
| | | fclose(fp); |
| | | |
| | | return res; |
| | | } |
| | | |
| | | int cp_string_write_file(cp_string *str, char *filename) |
| | | { |
| | | int rc; |
| | | FILE *fp = fopen(filename, "wb"); |
| | | if (fp == NULL) return 0; |
| | | |
| | | rc = cp_string_write(str, fileno(fp)); |
| | | fclose(fp); |
| | | |
| | | return rc; |
| | | } |
| | | |
| | | #define LINELEN 81 |
| | | #define CHARS_PER_LINE 16 |
| | | |
| | | static char *print_char = |
| | | " " |
| | | " " |
| | | " !\"#$%&'()*+,-./" |
| | | "0123456789:;<=>?" |
| | | "@ABCDEFGHIJKLMNO" |
| | | "PQRSTUVWXYZ[\\]^_" |
| | | "`abcdefghijklmno" |
| | | "pqrstuvwxyz{|}~ " |
| | | " " |
| | | " " |
| | | " ???????????????" |
| | | "????????????????" |
| | | "????????????????" |
| | | "????????????????" |
| | | "????????????????" |
| | | "????????????????"; |
| | | |
| | | void cp_cstring_dump(char *data, int len) |
| | | { |
| | | int rc; |
| | | int idx; |
| | | char prn[LINELEN]; |
| | | char lit[CHARS_PER_LINE + 1]; |
| | | char hc[4]; |
| | | short line_done = 1; |
| | | |
| | | rc = len; |
| | | idx = 0; |
| | | lit[CHARS_PER_LINE] = '\0'; |
| | | while (rc > 0) |
| | | { |
| | | if (line_done) |
| | | snprintf(prn, LINELEN, "%08X: ", idx); |
| | | do |
| | | { |
| | | unsigned char c = data[idx]; |
| | | snprintf(hc, 4, "%02X ", c); |
| | | strncat(prn, hc, 4); |
| | | lit[idx % CHARS_PER_LINE] = print_char[c]; |
| | | ++idx; |
| | | } while (--rc > 0 && (idx % CHARS_PER_LINE != 0)); |
| | | line_done = (idx % CHARS_PER_LINE) == 0; |
| | | if (line_done) |
| | | printf("%s %s\n", prn, lit); |
| | | else if (rc == 0) |
| | | strncat(prn, " ", LINELEN); |
| | | } |
| | | if (!line_done) |
| | | { |
| | | lit[(idx % CHARS_PER_LINE)] = '\0'; |
| | | while ((++idx % CHARS_PER_LINE) != 0) |
| | | strncat(prn, " ", LINELEN); |
| | | |
| | | printf("%s %s\n", prn, lit); |
| | | |
| | | } |
| | | } |
| | | |
| | | const char *cp_hexdump_string(const void *data, size_t len) |
| | | { |
| | | static char string[1024]; |
| | | unsigned char *d = (unsigned char *)data; |
| | | unsigned int i, left; |
| | | |
| | | string[0] = '\0'; |
| | | left = sizeof(string); |
| | | for (i = 0; len--; i += 3) { |
| | | if (i >= sizeof(string) - 4) |
| | | break; |
| | | snprintf(string + i, 4, " %02x", *d++); |
| | | } |
| | | |
| | | return string; |
| | | } |
| | | |
| | | |
| | | void cp_string_dump(cp_string *str) |
| | | { |
| | | int rc; |
| | | int idx; |
| | | char prn[LINELEN]; |
| | | char lit[CHARS_PER_LINE + 1]; |
| | | char hc[4]; |
| | | short line_done = 1; |
| | | |
| | | rc = str->len; |
| | | idx = 0; |
| | | lit[CHARS_PER_LINE] = '\0'; |
| | | while (rc > 0) |
| | | { |
| | | if (line_done) |
| | | snprintf(prn, LINELEN, "%08X: ", idx); |
| | | do |
| | | { |
| | | unsigned char c = str->data[idx]; |
| | | snprintf(hc, 4, "%02X ", c); |
| | | strncat(prn, hc, 4); |
| | | lit[idx % CHARS_PER_LINE] = print_char[c]; |
| | | ++idx; |
| | | } while (--rc > 0 && (idx % CHARS_PER_LINE != 0)); |
| | | line_done = (idx % CHARS_PER_LINE) == 0; |
| | | if (line_done) |
| | | printf("%s %s\n", prn, lit); |
| | | else if (rc == 0) |
| | | strncat(prn, " ", LINELEN); |
| | | } |
| | | if (!line_done) |
| | | { |
| | | lit[(idx % CHARS_PER_LINE)] = '\0'; |
| | | while ((++idx % CHARS_PER_LINE) != 0) |
| | | strncat(prn, " ", LINELEN); |
| | | |
| | | printf("%s %s\n", prn, lit); |
| | | } |
| | | } |
| | | |
| | | /** flip the contents of a cp_string */ |
| | | void cp_string_flip(cp_string *str) |
| | | { |
| | | if (str->len) |
| | | { |
| | | char *i, *f, ch; |
| | | f = &str->data[str->len - 1]; |
| | | i = str->data; |
| | | while (i < f) |
| | | { |
| | | ch = *i; |
| | | *i = *f; |
| | | *f = ch; |
| | | i++; |
| | | f--; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* remove all occurrences of letters from str */ |
| | | cp_string *cp_string_filter(cp_string *str, char *letters) |
| | | { |
| | | char *i; |
| | | char *f; |
| | | |
| | | str->data[str->len] = '\0'; |
| | | i = str->data; |
| | | while ((f = strpbrk(i, letters))) |
| | | { |
| | | i = f; |
| | | while (*f && strchr(letters, *f)) f++; |
| | | if (*f) |
| | | { |
| | | memmove(i, f, str->len - (f - str->data)); |
| | | str->len -= f - i; |
| | | str->data[str->len] = '\0'; |
| | | } |
| | | else |
| | | { |
| | | *i = '\0'; |
| | | str->len -= str->len - (i - str->data); |
| | | break; |
| | | } |
| | | } |
| | | |
| | | return str; |
| | | } |
| | | |
| | | /** @} */ |
| | | |
| | | |
| | | char *del_char_from_string(char *str, char delchar) |
| | | { |
| | | char *idx = str; |
| | | char *end = str; |
| | | while (*idx) |
| | | { |
| | | if (*idx == delchar) |
| | | { |
| | | ++idx; |
| | | } |
| | | else |
| | | { |
| | | *end = *idx; |
| | | ++end; |
| | | ++idx; |
| | | } |
| | | } |
| | | *end = '\0'; |
| | | return str; |
| | | } |
| | | |
| | | int split_string_to_value(char *str, char *fmt, ...) |
| | | { |
| | | va_list ap; |
| | | |
| | | int *iPtr; |
| | | long *lPtr; |
| | | char *pcPtr; |
| | | |
| | | char delim[2]={*(fmt+2), '\0'}; |
| | | char *result; |
| | | |
| | | va_start(ap, fmt); |
| | | |
| | | result = strtok( str, delim ); |
| | | |
| | | while(*fmt) |
| | | { |
| | | switch (*fmt++) |
| | | { |
| | | case 's': /* string */ |
| | | pcPtr = va_arg(ap, char *); |
| | | if(NULL!= result) |
| | | { |
| | | if(NULL!=pcPtr) |
| | | { |
| | | strcpy(pcPtr, result); |
| | | } |
| | | result = strtok( NULL, delim ); |
| | | } |
| | | else |
| | | goto OUT; |
| | | |
| | | break; |
| | | |
| | | case 'd': /* int */ |
| | | iPtr = va_arg(ap, int *); |
| | | if(NULL!= result) |
| | | { |
| | | if(NULL!=iPtr) |
| | | { |
| | | *iPtr = atoi(result); |
| | | } |
| | | result = strtok( NULL, delim ); |
| | | } |
| | | else |
| | | goto OUT; |
| | | |
| | | break; |
| | | |
| | | case 'l': /* long */ |
| | | lPtr = va_arg(ap, long *); |
| | | if(NULL!= result) |
| | | { |
| | | if(NULL!=lPtr) |
| | | { |
| | | *lPtr = strtol(result, NULL, 10); |
| | | } |
| | | result = strtok( NULL, delim ); |
| | | } |
| | | else |
| | | goto OUT; |
| | | |
| | | break; |
| | | |
| | | case 'x': /* long hex*/ |
| | | lPtr = va_arg(ap, long *); |
| | | if(NULL!= result) |
| | | { |
| | | if(NULL!=lPtr) |
| | | { |
| | | *lPtr = strtol(result, NULL, 16); |
| | | } |
| | | result = strtok( NULL, delim ); |
| | | } |
| | | else |
| | | goto OUT; |
| | | |
| | | break; |
| | | } |
| | | } |
| | | |
| | | OUT: |
| | | va_end(ap); |
| | | return 0; |
| | | } |
| | | |
New file |
| | |
| | | #ifndef _CP_STRING_H |
| | | #define _CP_STRING_H |
| | | |
| | | /** @{ */ |
| | | /** |
| | | * @file |
| | | * cp_string - 'safe' string allowing binary content |
| | | */ |
| | | |
| | | #include <stdio.h> |
| | | #include <string.h> |
| | | #include <stdlib.h> |
| | | #include <unistd.h> |
| | | #include <stdarg.h> |
| | | |
| | | /** cp_string definition */ |
| | | typedef struct _cp_string |
| | | { |
| | | int size; /**< size allocated */ |
| | | int len; /**< size used */ |
| | | char *data; /**< internal buffer */ |
| | | } cp_string; |
| | | |
| | | /** allocate a new cp_string */ |
| | | cp_string *cp_string_create(char *data, int len); |
| | | /** allocate an empty cp_string with a given buffer size */ |
| | | cp_string *cp_string_create_empty(int initial_size); |
| | | /** deallocate a cp_string */ |
| | | void cp_string_destroy(cp_string *str); |
| | | /** Sets string data to 0 */ |
| | | void cp_string_clear_data(cp_string *str); |
| | | /** copies the content of a null terminated c string */ |
| | | cp_string *cp_string_cstrcpy(cp_string *str, char *cstr); |
| | | /** copies the content of a cp_string */ |
| | | //cp_string *cp_string_cp(cp_string *dst, cp_string *src); |
| | | int cp_string_copy(cp_string *dst, cp_string *src); |
| | | int cp_string_move(cp_string *dst, cp_string *src); |
| | | /** copy the string into *dst */ |
| | | int cp_string_cstrcopy(cp_string *dst, char *string, int len); |
| | | /** creates a copy of src string. internal buffer is duplicated. */ |
| | | cp_string *cp_string_dup(cp_string *src); |
| | | /** creates a cp_string with src as its content */ |
| | | cp_string *cp_string_cstrdup(char *src); |
| | | /** concatenate cp_strings */ |
| | | cp_string *cp_string_cat(cp_string *str, cp_string *appendum); |
| | | /** append data from a buffer */ |
| | | cp_string *cp_string_cat_bin(cp_string *str, void *bin, int len); |
| | | /** append data from a null terminated c string */ |
| | | cp_string *cp_string_cstrcat(cp_string *str, char *cstr); |
| | | /** append a character to a string */ |
| | | cp_string *cp_string_append_char(cp_string *str, char ch); |
| | | /** compare cp_strings */ |
| | | int cp_string_cmp(cp_string *s1, cp_string *s2); |
| | | /** return a pointer to the internal buffer */ |
| | | char *cp_string_tocstr(cp_string *str); |
| | | /** return the length of the internal buffer */ |
| | | int cp_string_len(cp_string *s); |
| | | /** return the internal buffer */ |
| | | char *cp_string_data(cp_string *s); |
| | | |
| | | /** read len bytes from an open file descriptor (blocking) */ |
| | | cp_string *cp_string_read(int fd, int len); |
| | | /** write the content of a cp_string to a file descriptor (blocking) */ |
| | | int cp_string_write(cp_string *str, int fd); |
| | | /** read the contents of a file into a cp_string */ |
| | | cp_string *cp_string_read_file(char *filename); |
| | | /** write the contents of a cp_string to a file */ |
| | | int cp_string_write_file(cp_string *str, char *filename); |
| | | |
| | | /** flip the contents of a cp_string */ |
| | | void cp_string_flip(cp_string *str); |
| | | /** remove all occurrences of letters from str */ |
| | | cp_string *cp_string_filter(cp_string *str, char *letters); |
| | | |
| | | /** dump a cp_string to stdout */ |
| | | const char *cp_hexdump_string(const void *data, size_t len); |
| | | void cp_string_dump(cp_string *str); |
| | | void cp_cstring_dump(char *data, int len); |
| | | |
| | | char *del_char_from_string(char *str, char delchar); |
| | | int split_string_to_value(char *str, char *fmt, ...); |
| | | |
| | | /** @} */ |
| | | |
| | | #endif |
| | | |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2012 CoherentPlus Sdn. Bhd. |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_time.h |
| | | * Description: This head file |
| | | * |
| | | * Version: 1.0.0(02/23/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "02/23/2012 07:46:37 AM" |
| | | * |
| | | ********************************************************************************/ |
| | | #ifndef __CP_TIME_H |
| | | #define __CP_TIME_H |
| | | |
| | | #include <unistd.h> |
| | | #include <string.h> |
| | | #include <fcntl.h> |
| | | #include <time.h> |
| | | |
| | | #include <linux/rtc.h> |
| | | #include <sys/ioctl.h> |
| | | #include <sys/types.h> |
| | | #include <sys/stat.h> |
| | | #include <sys/time.h> |
| | | |
| | | typedef struct __DATE_TIME |
| | | { |
| | | int iYear; |
| | | int iMonth; |
| | | int iDay; |
| | | int iHour; |
| | | int iMinute; |
| | | int iSecond; |
| | | int iDayOfWeek; |
| | | } DATE_TIME; |
| | | |
| | | static inline void micro_second_sleep(unsigned long ms) |
| | | { |
| | | struct timespec cSleep; |
| | | unsigned long ulTmp; |
| | | cSleep.tv_sec = ms / 1000; |
| | | if (cSleep.tv_sec == 0) |
| | | { |
| | | ulTmp = ms * 10000; |
| | | cSleep.tv_nsec = ulTmp * 100; |
| | | } |
| | | else |
| | | { |
| | | cSleep.tv_nsec = 0; |
| | | } |
| | | |
| | | nanosleep(&cSleep, 0); |
| | | } |
| | | |
| | | /*UNIT: micro second*/ |
| | | static inline unsigned long time_now() |
| | | { |
| | | struct timeval now; |
| | | gettimeofday(&now, 0); |
| | | return (now.tv_sec * 1000) + (now.tv_usec / 1000); |
| | | } |
| | | |
| | | /*UNIT: micro second*/ |
| | | static inline unsigned long time_elapsed(unsigned long start) |
| | | { |
| | | unsigned long current = time_now(); |
| | | |
| | | if (current < start) |
| | | { |
| | | return (0xFFFFFFFF - start) + current; |
| | | } |
| | | |
| | | //printf("time_elapsed: %ld\n", current-start); |
| | | return current - start; |
| | | } |
| | | |
| | | static inline void get_current_time(DATE_TIME * date) |
| | | { |
| | | time_t now = time(NULL); |
| | | struct tm *tnow = localtime(&now); |
| | | |
| | | memset(date, 0, sizeof(DATE_TIME)); |
| | | date->iYear = 1900 + tnow->tm_year; |
| | | date->iMonth = 1 + tnow->tm_mon; |
| | | date->iDay = tnow->tm_mday; |
| | | |
| | | date->iHour = tnow->tm_hour; |
| | | date->iMinute = tnow->tm_min; |
| | | date->iSecond = tnow->tm_sec; |
| | | date->iDayOfWeek = tnow->tm_wday; |
| | | return; |
| | | } |
| | | #define get_sys_time(date) get_current_time(date) |
| | | |
| | | static inline int get_rtc_time(DATE_TIME *date) |
| | | { |
| | | int rv, fd = -1; |
| | | struct rtc_time rtc_tm; |
| | | |
| | | memset(date, 0, sizeof(DATE_TIME)); |
| | | |
| | | if ((fd=open("/dev/rtc0", O_RDONLY)) < 0) |
| | | return -1; |
| | | |
| | | if((rv=ioctl(fd, RTC_RD_TIME, &rtc_tm)) < 0) |
| | | return -2; |
| | | |
| | | date->iYear = 1900 + rtc_tm.tm_year; |
| | | date->iMonth = 1 + rtc_tm.tm_mon; |
| | | date->iDay = rtc_tm.tm_mday; |
| | | |
| | | date->iHour = rtc_tm.tm_hour; |
| | | date->iMinute = rtc_tm.tm_min; |
| | | date->iSecond = rtc_tm.tm_sec; |
| | | date->iDayOfWeek = rtc_tm.tm_wday; |
| | | |
| | | close(fd); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | #endif |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_vector.c |
| | | * Description: This file is for a dynamic array |
| | | * |
| | | * Version: 1.0.0(11/12/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "11/12/2012 11:20:30 AM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include <stdio.h> |
| | | #include <unistd.h> |
| | | #include <stdlib.h> |
| | | #include <string.h> |
| | | |
| | | #include "cp_vector.h" |
| | | #include "cp_common.h" |
| | | |
| | | CP_VECTOR *cp_vector_init(int size) |
| | | { |
| | | CP_VECTOR *vector = NULL; |
| | | if(size < 0) |
| | | return NULL; |
| | | |
| | | vector = (CP_VECTOR *)t_malloc(sizeof(CP_VECTOR)); |
| | | if(!vector) |
| | | { |
| | | return NULL; |
| | | } |
| | | |
| | | vector->mem = t_malloc(size*sizeof(void *)); |
| | | if(!vector->mem) |
| | | { |
| | | t_free(vector); |
| | | return NULL; |
| | | } |
| | | |
| | | memset(vector->mem, 0, size); |
| | | vector->size = size; |
| | | vector->used = 0; |
| | | |
| | | return vector; |
| | | } |
| | | |
| | | void *cp_vector_add(CP_VECTOR *vector, int index, void *item) |
| | | { |
| | | if(index<0 || index>vector->size) |
| | | return NULL; |
| | | |
| | | vector->mem[index]=item; |
| | | vector->used++; |
| | | |
| | | return item; |
| | | } |
| | | |
| | | void *cp_vector_del(CP_VECTOR *vector, int index) |
| | | { |
| | | void *save; |
| | | |
| | | if(index<0 ||index>vector->size) |
| | | return NULL; |
| | | |
| | | save = vector->mem[index]; |
| | | |
| | | vector->mem[index]=NULL; |
| | | vector->used--; |
| | | |
| | | return save; |
| | | } |
| | | |
| | | void *cp_vector_get(CP_VECTOR *vector, int index) |
| | | { |
| | | if(index<0 ||index>vector->size) |
| | | return NULL; |
| | | |
| | | return vector->mem[index]; |
| | | } |
| | | |
| | | void cp_vector_destroy(CP_VECTOR *vector) |
| | | { |
| | | if(!vector) |
| | | return; |
| | | |
| | | if(vector->mem) |
| | | { |
| | | t_free(vector->mem); |
| | | } |
| | | |
| | | t_free(vector); |
| | | } |
| | | |
| | | |
| | | |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: cp_vector.h |
| | | * Description: This head file is for dynamic array |
| | | * |
| | | * Version: 1.0.0(11/12/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "11/12/2012 11:20:53 AM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #ifndef __CP_VECTOR |
| | | #define __CP_VECTOR |
| | | |
| | | #include <stdio.h> |
| | | #include <unistd.h> |
| | | #include <stdlib.h> |
| | | #include <string.h> |
| | | |
| | | typedef struct _CP_VECTOR |
| | | { |
| | | int size; |
| | | int used; |
| | | void **mem; |
| | | } CP_VECTOR; |
| | | |
| | | #define cp_vector_count(v) ((v) ? (v)->used : 0) |
| | | #define cp_vector_size(v) ((v) ? (v)->size : 0) |
| | | |
| | | CP_VECTOR *cp_vector_init(int size); |
| | | void *cp_vector_add(CP_VECTOR *vector, int index, void *item); |
| | | void *cp_vector_del(CP_VECTOR *vector, int index); |
| | | void *cp_vector_get(CP_VECTOR *vector, int index); |
| | | void cp_vector_destroy(CP_VECTOR *vector); |
| | | |
| | | #endif |
| | | |
| | | |
New file |
| | |
| | | #********************************************************************************* |
| | | # Copyright: (C) 2012 Guo Wenxue <guowenxue@gmail.com> |
| | | # All rights reserved. |
| | | # |
| | | # Filename: Makefile |
| | | # Description: This is the common subdir Makefile which to compile all the C |
| | | # source code to object files and then generate the shared or |
| | | # static library named lib$(FOLDER_NAME).a orlib $(FOLDER_NAME).so, |
| | | # which depends on the variable $LINK_MODE. |
| | | # |
| | | # Version: 1.0.0(10/08/2011~) |
| | | # Author: Guo Wenxue <guowenxue@gmail.com> |
| | | # ChangeLog: 1, Release initial version on "10/08/2011 01:29:33 AM" |
| | | # |
| | | #********************************************************************************/ |
| | | |
| | | PWD=$(shell pwd) |
| | | |
| | | #If wanna compile in the subdir, not called by top makefile, uncomment it |
| | | ifneq (${TOP_COMPILE}, YES) |
| | | LOCAL_COMPILE=YES |
| | | endif |
| | | |
| | | LINK_MODE=STATIC |
| | | #MULTHREADS=YES |
| | | |
| | | LIBNAME=$(shell basename ${PWD}) |
| | | STALIB=lib${LIBNAME}.a |
| | | DYNLIB=lib${LIBNAME}.so |
| | | |
| | | VPATH= . |
| | | SRCS = $(wildcard ${VPATH}/*.c) |
| | | OBJS = $(patsubst %.c,%.o,$(SRCS)) |
| | | |
| | | #====================================================== |
| | | # ---> Doesn't call by top makefile, compile by local |
| | | #====================================================== |
| | | ifeq (${LOCAL_COMPILE}, YES) |
| | | ARCH?=arm920t |
| | | #ARCH?=i386 |
| | | CFLAGS+=-fPIC |
| | | TMP=$(shell echo $(ARCH) | tr "[A-Z]" "[a-z]") |
| | | ifneq (,$(filter i386,$(TMP))) |
| | | CROSS_COMPILE= |
| | | else |
| | | CROSS_COMPILE=/opt/xtools/arm920t/bin/arm-linux- |
| | | endif |
| | | |
| | | PRJDIR?=$(shell dirname ${PWD}) |
| | | CFLAGS+=-I${PRJDIR} -g -Wall -Werror |
| | | CC = ${CROSS_COMPILE}gcc |
| | | AR = ${CROSS_COMPILE}ar |
| | | |
| | | endif #End local compile |
| | | |
| | | ifeq ("${LINK_MODE}", "STATIC") |
| | | LIBS = ${STALIB} |
| | | else |
| | | LIBS=${DYNLIB} ${STALIB} |
| | | endif |
| | | |
| | | ifeq ("${MULTHREADS}", "YES") |
| | | LDFLAGS+=-lpthread |
| | | CFLAGS+=-DMULTHREADS |
| | | endif |
| | | |
| | | all: entry clean ${LIBS} install |
| | | |
| | | entry: |
| | | @echo " "; |
| | | @echo " ========================================================="; |
| | | @echo " ** Compile subdir ${LIBNAME} for ${ARCH} "; |
| | | @echo " ========================================================="; |
| | | |
| | | #$(LD) -g --relocatable $(OBJS) -o lib${LIBNAME}.o |
| | | ${STALIB}: $(OBJS) |
| | | $(AR) -rcu $@ $(OBJS) |
| | | |
| | | ${DYNLIB}: $(OBJS) |
| | | $(CC) -fPIC -shared -o $@ $(OBJS) |
| | | |
| | | %.o : %.c |
| | | $(CC) -c $< $(CFLAGS) |
| | | |
| | | test: clean ${LIBS} |
| | | make -C test ARCH=${ARCH} |
| | | |
| | | tag: |
| | | @ctags --c-kinds=+defglmnstuvx --langmap=c:.c.h.ho.hem.het.hec.hev.him.hit.hic.hiv -R . |
| | | @cscope -Rbq |
| | | |
| | | install: |
| | | @if [ ! -z "${LIBS_PATH}" ] ; then \ |
| | | mkdir -p ${LIBS_PATH} ; \ |
| | | cp ${LIBS} ${LIBS_PATH}; \ |
| | | fi; |
| | | |
| | | clean: |
| | | @rm -f *.o *.lo *~ |
| | | @rm -rf *.gdb *.a *.so |
| | | @make clean -C test |
| | | @rm -f *.log |
| | | |
| | | distclean: clean |
| | | @rm -f tags cscope* |
| | | |
| | | .PHONY: clean entry |
New file |
| | |
| | | !_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ |
| | | !_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ |
| | | !_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/ |
| | | !_TAG_PROGRAM_NAME Exuberant Ctags // |
| | | !_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ |
| | | !_TAG_PROGRAM_VERSION 5.9~svn20110310 // |
| | | ALL_READY cp_gprs.h /^ ALL_READY,$/;" e enum:__anon4 |
| | | APN_2G cp_ppp.h 31;" d |
| | | APN_3G cp_ppp.h 30;" d |
| | | APN_ACCOUNT cp_ppp.h /^} APN_ACCOUNT; $/;" t typeref:struct:__APN_ACCOUNT |
| | | APN_DEF_CONF_FILE cp_ppp.h 39;" d |
| | | APN_LEN cp_ppp.h 26;" d |
| | | AR makefile /^AR = ${CROSS_COMPILE}ar$/;" m |
| | | AR test/makefile /^export AR=${CROSS_COMPILE}ar$/;" m |
| | | ARCH makefile /^ARCH?=arm920t$/;" m |
| | | ARCH test/makefile /^ARCH?=arm920t$/;" m |
| | | ARCH_HAS_PREFETCH cp_klist.h 54;" d |
| | | AS test/makefile /^export AS=${CROSS_COMPILE}as$/;" m |
| | | ASCIILINESZ cp_iniparser.c 14;" d file: |
| | | ATCMD_REPLY_LEN cp_atcmd.c 20;" d file: |
| | | BINARIES test/makefile /^BINARIES=$(SRCFILES:%.c=%)$/;" m |
| | | BLINK cp_hal.h 35;" d |
| | | BUF_64 cp_comport.h 30;" d |
| | | BUZZER_BEEP at91_ioctl.h 50;" d |
| | | BUZZER_FREQ at91_ioctl.h 52;" d |
| | | BUZZER_OFF at91_ioctl.h 51;" d |
| | | BUZZER_ON at91_ioctl.h 49;" d |
| | | CC makefile /^CC = ${CROSS_COMPILE}gcc$/;" m |
| | | CC test/makefile /^export CC=${CROSS_COMPILE}gcc$/;" m |
| | | CHARS_PER_LINE cp_logger.c 343;" d file: |
| | | CHARS_PER_LINE cp_string.c 397;" d file: |
| | | CHECK_HWINFO cp_gprs.h /^ CHECK_HWINFO, \/* Get GPRS hardware Information *\/$/;" e enum:__anon4 |
| | | CHECK_REGISTRY cp_gprs.h /^ CHECK_REGISTRY, \/* Check GPRS register network information *\/$/;" e enum:__anon4 |
| | | CHUNK cp_string.c 317;" d file: |
| | | CMUX_DATAPORT cp_gprs.h 37;" d |
| | | CMUX_PORT_START_INDEX cp_gprs.h 36;" d |
| | | COMPILE_DATE test/makefile /^COMPILE_DATE=$(shell date -u +"%Y-%m-%d %H:%M")$/;" m |
| | | COM_PORT cp_comport.h /^} COM_PORT;$/;" t typeref:struct:__COM_PORT |
| | | COM_PRINT cp_comport.h 38;" d |
| | | COM_PRINT cp_comport.h 40;" d |
| | | CONNECTED cp_ppp.h /^ CONNECTED,$/;" e enum:__anon2 |
| | | CONNECTING cp_ppp.h /^ CONNECTING,$/;" e enum:__anon2 |
| | | CP_ARRAY cp_array.h /^} CP_ARRAY;$/;" t typeref:struct:_CP_ARRAY |
| | | CP_ARRAY_FLAG_MALLOC cp_array.h 17;" d |
| | | CP_DEF_FDS_TIMEOUT cp_fds.h 33;" d |
| | | CP_DEF_MAX_CLIENTS cp_network.h 19;" d |
| | | CP_DEF_MAX_EVENTS cp_fds.h 32;" d |
| | | CP_DEF_RCVBUF_SIZE cp_sock.h 39;" d |
| | | CP_DEF_SNDBUF_SIZE cp_sock.h 40;" d |
| | | CP_DEF_TIMEOUT cp_network.h 20;" d |
| | | CP_FDS cp_fds.h /^} CP_FDS;$/;" t typeref:struct:_CP_FDS |
| | | CP_LOGGER_ARGUMENT cp_logger.h 62;" d |
| | | CP_LOGGER_CONSOLE cp_logger.h 64;" d |
| | | CP_LOGGER_FILE cp_logger.h 65;" d |
| | | CP_LOGGER_LEVEL_OPT cp_logger.h 67;" d |
| | | CP_LOGGER_MALLOC cp_logger.h 61;" d |
| | | CP_MAX_EVENT_ONCE cp_fds.h 31;" d |
| | | CP_PROC_SIG cp_proc.h /^} CP_PROC_SIG;$/;" t typeref:struct:__CP_PROC_SIG |
| | | CP_QNODE cp_queue.h /^} CP_QNODE;$/;" t typeref:struct:_CP_QNODE |
| | | CP_QUEUE cp_queue.h /^} CP_QUEUE;$/;" t typeref:struct:_CP_QUEUE |
| | | CP_SOCK cp_sock.h /^} CP_SOCK;$/;" t typeref:struct:_CP_SOCK |
| | | CP_SOCK_CALLBACK cp_sock.h /^} CP_SOCK_CALLBACK; $/;" t typeref:struct:_CP_SOCK_CALLBACK |
| | | CP_SOCK_DEF_IDLE_TIMEOUT cp_sock.h 45;" d |
| | | CP_SOCK_DEF_MSG_TIMEOUT cp_sock.h 46;" d |
| | | CP_SOCK_EVENT_CALLBACK cp_sock.h /^typedef int (*CP_SOCK_EVENT_CALLBACK)(struct _CP_SOCK *sock);$/;" t |
| | | CP_SOCK_EVENT_ERROR cp_sock.h /^ CP_SOCK_EVENT_ERROR = EPOLLERR, \/* compatilbe with EPOLLERR *\/$/;" e enum:__anon7 |
| | | CP_SOCK_EVENT_HUP cp_sock.h /^ CP_SOCK_EVENT_HUP = EPOLLHUP, \/* compatilbe with EPOLLHUP *\/$/;" e enum:__anon7 |
| | | CP_SOCK_EVENT_IDLE_TIMEOUT cp_sock.h /^ CP_SOCK_EVENT_IDLE_TIMEOUT = (1<<16), \/* compatilbe with EPOLL reserved*\/ $/;" e enum:__anon7 |
| | | CP_SOCK_EVENT_MSG_TIMEOUT cp_sock.h /^ CP_SOCK_EVENT_MSG_TIMEOUT = (1<<17), \/* compatible with EPOLL reserved*\/$/;" e enum:__anon7 |
| | | CP_SOCK_EVENT_READ cp_sock.h /^ CP_SOCK_EVENT_READ = EPOLLIN, \/* compatilbe with EPOLLIN *\/$/;" e enum:__anon7 |
| | | CP_SOCK_EVENT_WRITE cp_sock.h /^ CP_SOCK_EVENT_WRITE = EPOLLOUT, \/* compatilbe with EPOLLOUT *\/$/;" e enum:__anon7 |
| | | CP_SOCK_KEEPCNT cp_sock.h 49;" d |
| | | CP_SOCK_KEEPINTVL cp_sock.h 48;" d |
| | | CP_SOCK_MODE_ACCEPT cp_sock.h 52;" d |
| | | CP_SOCK_MODE_CONNECT cp_sock.h 53;" d |
| | | CP_SOCK_MODE_LISTEN cp_sock.h 54;" d |
| | | CP_SOCK_MODE_NONE cp_sock.h 51;" d |
| | | CP_SOCK_RCVBUF cp_sock.h 42;" d |
| | | CP_SOCK_SNDBUF cp_sock.h 43;" d |
| | | CP_VECTOR cp_vector.h /^} CP_VECTOR;$/;" t typeref:struct:_CP_VECTOR |
| | | CROSS_COMPILE makefile /^ CROSS_COMPILE=$/;" m |
| | | CROSS_COMPILE makefile /^ CROSS_COMPILE=\/opt\/xtools\/arm920t\/bin\/arm-linux-$/;" m |
| | | CROSS_COMPILE test/makefile /^ CROSS_COMPILE=$/;" m |
| | | CROSS_COMPILE test/makefile /^ CROSS_COMPILE=\/opt\/buildroot-2012.08\/$(ARCH)\/usr\/bin\/arm-linux-$/;" m |
| | | CXX test/makefile /^export CXX=${CROSS_COMPILE}g++$/;" m |
| | | DATE_TIME cp_time.h /^} DATE_TIME;$/;" t typeref:struct:__DATE_TIME |
| | | DBG_LOG_FILE cp_logger.h 37;" d |
| | | DEBUG test/makefile /^DEBUG=1$/;" m |
| | | DEFAULT_LOGFILE cp_logger.h 36;" d |
| | | DEFAULT_PING_INTERVAL cp_ppp.h 25;" d |
| | | DEFAULT_TIME_FORMAT cp_logger.h 42;" d |
| | | DEF_PING_DST cp_ppp.h 37;" d |
| | | DEVNAME_LEN cp_comport.h 33;" d |
| | | DEV_GMTUBE_PATH cp_hal.h 31;" d |
| | | DEV_GPS_PATH cp_hal.h 29;" d |
| | | DEV_GSM_PATH cp_hal.h 28;" d |
| | | DEV_LED_PATH cp_hal.h 27;" d |
| | | DEV_ZIGBEE_PATH cp_hal.h 30;" d |
| | | DICTMINSZ cp_dictionary.c 27;" d file: |
| | | DICT_INVALID_KEY cp_dictionary.c 30;" d file: |
| | | DISCONNECT cp_ppp.h /^ DISCONNECT = 0,$/;" e enum:__anon2 |
| | | DOMAIN test/test_sock_server.c 23;" d file: |
| | | DYNLIB makefile /^DYNLIB=lib${LIBNAME}.so$/;" m |
| | | FILENAME_LEN cp_logger.h 33;" d |
| | | FLAG_FDS_INIT cp_fds.h 38;" d |
| | | FLAG_FDS_MALLOC cp_fds.h 39;" d |
| | | FLAG_SOCK_EPOLLED cp_sock.h 81;" d |
| | | FLAG_SOCK_INIT cp_sock.h 79;" d |
| | | FLAG_SOCK_INQUEUE cp_sock.h 83;" d |
| | | FLAG_SOCK_MALLOC cp_sock.h 80;" d |
| | | FLAG_SOCK_REGISTRY cp_sock.h 82;" d |
| | | FLAG_SOCK_TASKED cp_sock.h 84;" d |
| | | FLAG_TPDU_INIT test/swe_tpdud.h 26;" d |
| | | FLAG_TPDU_STOP test/swe_tpdud.h 27;" d |
| | | GET_ADC_DATA at91_ioctl.h 44;" d |
| | | GET_BATTERY_STAT at91_ioctl.h 41;" d |
| | | GET_BUTTON_STATUS at91_ioctl.h 55;" d |
| | | GET_DRV_VER at91_ioctl.h 34;" d |
| | | GET_GMTUBE_VHIGH at91_ioctl.h 42;" d |
| | | GET_GPRS_VBAT at91_ioctl.h 43;" d |
| | | GM_GET_MEASURE_DOSE at91_ioctl.h 81;" d |
| | | GM_GET_VOLTAGE at91_ioctl.h 84;" d |
| | | GM_SET_DUTY at91_ioctl.h 82;" d |
| | | GM_SET_INTERVAL at91_ioctl.h 83;" d |
| | | GM_SET_MEASURE_RADI at91_ioctl.h 80;" d |
| | | GM_SET_MEASURE_TC at91_ioctl.h 88;" d |
| | | GM_SET_POWER at91_ioctl.h 86;" d |
| | | GM_SET_PWM_TC at91_ioctl.h 87;" d |
| | | GM_SET_TIMER_TC at91_ioctl.h 89;" d |
| | | GPRS_LOCATION cp_atcmd.h /^} GPRS_LOCATION;$/;" t typeref:struct:_GPRS_LOCATION |
| | | GPS_GET_POWER at91_ioctl.h 75;" d |
| | | GPS_SET_POWER at91_ioctl.h 74;" d |
| | | GSMIOC_GETCONF cp_gsmmux.h 36;" d |
| | | GSMIOC_SETCONF cp_gsmmux.h 37;" d |
| | | GSM_CTRLPORT cp_gprs.h 32;" d |
| | | GSM_DATAPORT cp_gprs.h 33;" d |
| | | GSM_GET_ADC at91_ioctl.h 72;" d |
| | | GSM_GET_POWER at91_ioctl.h 71;" d |
| | | GSM_SET_POWER at91_ioctl.h 70;" d |
| | | HAL_LIBRARY_TEST test/test_hal.c 18;" d file: |
| | | HH_DATAPORT test/test_hh.c 16;" d file: |
| | | HLIST_HEAD cp_klist.h 587;" d |
| | | HLIST_HEAD_INIT cp_klist.h 586;" d |
| | | HOSTSIM_IP test/swe_tpdud.h 20;" d |
| | | HOSTSIM_PORT test/swe_tpdud.h 19;" d |
| | | HW_INFO cp_atcmd.h /^} HW_INFO;$/;" t typeref:struct:_HARDWARE_INFO |
| | | INIT_HLIST_HEAD cp_klist.h 588;" d |
| | | INIT_HLIST_NODE cp_klist.h /^static inline void INIT_HLIST_NODE(struct hlist_node *h)$/;" f |
| | | INIT_LIST_HEAD cp_klist.h /^static inline void INIT_LIST_HEAD(struct list_head *list)$/;" f |
| | | INI_CONF test/test_ini.c 17;" d file: |
| | | INI_INVALID_KEY cp_iniparser.c 15;" d file: |
| | | INSTPATH test/makefile /^INSTPATH=\/tftp$/;" m |
| | | IN_EVENT_LIST cp_fds.h 35;" d |
| | | IN_TASK_LIST cp_fds.h 36;" d |
| | | IPADDR test/test_sock_server.c 24;" d file: |
| | | LED_BLINK at91_ioctl.h 60;" d |
| | | LED_OFF at91_ioctl.h 58;" d |
| | | LED_ON at91_ioctl.h 59;" d |
| | | LED_SYS cp_hal.h 44;" d |
| | | LIBNAME makefile /^LIBNAME=$(shell basename ${PWD})$/;" m |
| | | LIBS makefile /^ LIBS = ${STALIB} $/;" m |
| | | LIBS makefile /^ LIBS=${DYNLIB} ${STALIB}$/;" m |
| | | LIB_NAME test/makefile /^LIB_NAME=$(shell basename ${LIB_PATH})$/;" m |
| | | LIB_PATH test/makefile /^LIB_PATH=$(shell dirname ${PWD})$/;" m |
| | | LINELEN cp_logger.c 342;" d file: |
| | | LINELEN cp_string.c 396;" d file: |
| | | LINE_COMMENT cp_iniparser.c /^ LINE_COMMENT,$/;" e enum:_line_status_ file: |
| | | LINE_EMPTY cp_iniparser.c /^ LINE_EMPTY,$/;" e enum:_line_status_ file: |
| | | LINE_ERROR cp_iniparser.c /^ LINE_ERROR,$/;" e enum:_line_status_ file: |
| | | LINE_SECTION cp_iniparser.c /^ LINE_SECTION,$/;" e enum:_line_status_ file: |
| | | LINE_UNPROCESSED cp_iniparser.c /^ LINE_UNPROCESSED,$/;" e enum:_line_status_ file: |
| | | LINE_VALUE cp_iniparser.c /^ LINE_VALUE$/;" e enum:_line_status_ file: |
| | | LINK_MODE makefile /^LINK_MODE=STATIC$/;" m |
| | | LIST_HEAD cp_klist.h 74;" d |
| | | LIST_HEAD_INIT cp_klist.h 72;" d |
| | | LIST_POISON1 cp_klist.h 50;" d |
| | | LIST_POISON2 cp_klist.h 51;" d |
| | | LOCAL_COMPILE makefile /^LOCAL_COMPILE=YES$/;" m |
| | | LOG_FILE_LINE cp_logger.h 46;" d |
| | | LOG_LEVEL_DEBUG cp_logger.h /^ LOG_LEVEL_DEBUG, \/* Debug Level "Debug" *\/$/;" e enum:__anon1 |
| | | LOG_LEVEL_DISB cp_logger.h /^ LOG_LEVEL_DISB = 0, \/* Disable "Debug" *\/$/;" e enum:__anon1 |
| | | LOG_LEVEL_ERROR cp_logger.h /^ LOG_LEVEL_ERROR, \/* Debug Level "ERROR" *\/$/;" e enum:__anon1 |
| | | LOG_LEVEL_FATAL cp_logger.h /^ LOG_LEVEL_FATAL, \/* Debug Level "Fatal" *\/$/;" e enum:__anon1 |
| | | LOG_LEVEL_INFO cp_logger.h /^ LOG_LEVEL_INFO, \/* Debug Level "Information" *\/$/;" e enum:__anon1 |
| | | LOG_LEVEL_MAX cp_logger.h /^ LOG_LEVEL_MAX,$/;" e enum:__anon1 |
| | | LOG_LEVEL_NRML cp_logger.h /^ LOG_LEVEL_NRML, \/* Debug Level "Normal" *\/$/;" e enum:__anon1 |
| | | LOG_LEVEL_TRACE cp_logger.h /^ LOG_LEVEL_TRACE, \/* Debug Level "Trace" *\/$/;" e enum:__anon1 |
| | | LOG_LEVEL_WARN cp_logger.h /^ LOG_LEVEL_WARN, \/* Debug Level "warnning" *\/$/;" e enum:__anon1 |
| | | LOG_ROLLBACK_NONE cp_logger.h 40;" d |
| | | LOG_ROLLBACK_SIZE cp_logger.h 39;" d |
| | | LOG_VERSION_STR cp_logger.h 30;" d |
| | | MAXVALSZ cp_dictionary.c 24;" d file: |
| | | MAX_DATAPORT cp_gprs.h 35;" d |
| | | MAX_ITEMS test/test_array.c 22;" d file: |
| | | MAX_ITEMS test/test_queue.c 21;" d file: |
| | | MAX_LOG_MESSAGE_LEN cp_logger.h 43;" d |
| | | MAX_PPP_FAIL_CNT cp_ppp.h 99;" d |
| | | MODE test/makefile /^MODE=PRODUCTION$/;" m |
| | | MODE_AUTO cp_gprs.h 70;" d |
| | | MODE_FAST cp_hal.h 39;" d |
| | | MODE_GSM cp_gprs.h 71;" d |
| | | MODE_SLOW cp_hal.h 38;" d |
| | | MODE_WCDMA cp_gprs.h 72;" d |
| | | MODULE_INFO cp_gprs.h /^} MODULE_INFO;$/;" t typeref:struct:__MODULE_INFO |
| | | MODULE_READY cp_gprs.h /^ MODULE_READY, \/* GPRS AT command active and SIM card valid *\/$/;" e enum:__anon4 |
| | | NO cp_gprs.h 30;" d |
| | | NOT_READY cp_gprs.h /^ NOT_READY,$/;" e enum:__anon4 |
| | | NS_EGPRS cp_gprs.h /^ NS_EGPRS, \/* EGPRS(EDGE) *\/$/;" e enum:__anon6 |
| | | NS_GPRS cp_gprs.h /^ NS_GPRS, \/* GPRS *\/$/;" e enum:__anon6 |
| | | NS_GSM cp_gprs.h /^ NS_GSM, \/* GSM *\/$/;" e enum:__anon6 |
| | | NS_HSDPA cp_gprs.h /^ NS_HSDPA, \/* HSDPA only *\/$/;" e enum:__anon6 |
| | | NS_HSPA cp_gprs.h /^ NS_HSPA, \/* HSDPA and HSUPA *\/$/;" e enum:__anon6 |
| | | NS_HSUPA cp_gprs.h /^ NS_HSUPA, \/* HSUPA only *\/$/;" e enum:__anon6 |
| | | NS_NONE cp_gprs.h /^ NS_NONE = 0, \/* No service *\/$/;" e enum:__anon6 |
| | | NS_WCDMA cp_gprs.h /^ NS_WCDMA, \/* WCDMA *\/$/;" e enum:__anon6 |
| | | NVALS cp_dictionary.c 359;" d file: |
| | | N_GSM0710 cp_gsmmux.h 39;" d |
| | | OBJS makefile /^OBJS = $(patsubst %.c,%.o,$(SRCS))$/;" m |
| | | OBJS test/makefile /^OBJS = $(patsubst %.c,%.o,$(SRCS))$/;" m |
| | | OFF cp_hal.h 33;" d |
| | | ON cp_hal.h 34;" d |
| | | PID_ASCII_SIZE cp_proc.h 19;" d |
| | | PING_INTERVAL_TIME cp_ppp.h 23;" d |
| | | PLATDRV_MAGIC at91_ioctl.h 26;" d |
| | | POISON_POINTER_DELTA cp_klist.h 40;" d |
| | | POISON_POINTER_DELTA cp_klist.h 42;" d |
| | | PPPD_CMD_LEN cp_ppp.c 242;" d file: |
| | | PPPD_DIAL_SCRIPTS cp_ppp.h 33;" d |
| | | PPPD_DIAL_TIMEOUT cp_ppp.h 22;" d |
| | | PPPD_INFO cp_ppp.h /^} PPPD_INFO;$/;" t typeref:struct:__PPPD_INFO |
| | | PPP_BAD cp_ppp.h 104;" d |
| | | PPP_CONN cp_ppp.h 103;" d |
| | | PPP_CTX cp_ppp.h /^} PPP_CTX;$/;" t typeref:struct:__PPP_CTX |
| | | PPP_GOOD cp_ppp.h 105;" d |
| | | PPP_INTERFACE_NAME cp_ppp.h 34;" d |
| | | PPP_PROC_NET_DEV cp_ppp.h 35;" d |
| | | PPP_STAT cp_ppp.h /^} PPP_STAT;$/;" t typeref:struct:__PPP_STAT |
| | | PPP_STOP cp_ppp.h 101;" d |
| | | PRECISE_TIME_FACTOR cp_logger.c 17;" d file: |
| | | PRIVT_FREE cp_sock.h /^typedef void (*PRIVT_FREE)(void);$/;" t |
| | | PRJDIR makefile /^PRJDIR?=$(shell dirname ${PWD})$/;" m |
| | | PWD makefile /^PWD=$(shell pwd)$/;" m |
| | | PWD test/makefile /^PWD=$(shell pwd)$/;" m |
| | | PWD_LEN cp_ppp.h 28;" d |
| | | RANLIB test/makefile /^export RANLIB=${CROSS_COMPILE}ranlib$/;" m |
| | | REGISTER_INFO cp_atcmd.h /^} REGISTER_INFO;$/;" t typeref:struct:_REGISTER_INFO |
| | | REG_DENIED cp_gprs.h /^ REG_DENIED, \/* registration denied *\/$/;" e enum:__anon5 |
| | | REG_HOMEWORK cp_gprs.h /^ REG_HOMEWORK, \/* registered, home network *\/$/;" e enum:__anon5 |
| | | REG_ROAMING cp_gprs.h /^ REG_ROAMING, \/* registered, roaming *\/$/;" e enum:__anon5 |
| | | REG_SEARCHING cp_gprs.h /^ REG_SEARCHING, \/* not registered, but ME is currently searching a new operator to register to *\/$/;" e enum:__anon5 |
| | | REG_UNKNOW cp_gprs.h /^ REG_UNKNOW, \/* unknow *\/$/;" e enum:__anon5 |
| | | REG_UNREGIST cp_gprs.h /^ REG_UNREGIST = 0, \/* not registered, ME is not currently searching a new operator to register to *\/$/;" e enum:__anon5 |
| | | REQ_EVENT_NONE cp_gprs.h /^ REQ_EVENT_NONE = 0,$/;" e enum:__anon3 |
| | | REQ_POWER_OFF cp_gprs.h /^ REQ_POWER_OFF,$/;" e enum:__anon3 |
| | | REQ_POWER_ON cp_gprs.h /^ REQ_POWER_ON,$/;" e enum:__anon3 |
| | | REQ_POWER_RESET cp_gprs.h /^ REQ_POWER_RESET,$/;" e enum:__anon3 |
| | | RESET cp_hal.h 36;" d |
| | | SELECTED_APN cp_ppp.h /^ SELECTED_APN,$/;" e enum:__anon2 |
| | | SERV_ADDR test/test_sock_client.c 21;" d file: |
| | | SERV_PORT test/test_sock_client.c 23;" d file: |
| | | SERV_PORT1 test/test_sock_server.c 20;" d file: |
| | | SERV_PORT2 test/test_sock_server.c 21;" d file: |
| | | SET_ADC_INTERVEL at91_ioctl.h 45;" d |
| | | SET_DRV_DEBUG at91_ioctl.h 33;" d |
| | | SIG_WEAK cp_ppp.h 102;" d |
| | | SOCK_STAT_ACCEPTED cp_sock.h 90;" d |
| | | SOCK_STAT_ALREADY cp_sock.h 91;" d |
| | | SOCK_STAT_CONNECTED cp_sock.h 88;" d |
| | | SOCK_STAT_CONNECTING cp_sock.h 87;" d |
| | | SOCK_STAT_DISCONNECT cp_sock.h 92;" d |
| | | SOCK_STAT_INIT cp_sock.h 86;" d |
| | | SOCK_STAT_LISTENED cp_sock.h 89;" d |
| | | SRCFILES test/makefile /^SRCFILES = $(wildcard *.c)$/;" m |
| | | SRCS makefile /^SRCS = $(wildcard ${VPATH}\/*.c)$/;" m |
| | | SRCS test/makefile /^SRCS = $(wildcard ${VPATH}\/*.c)$/;" m |
| | | STALIB makefile /^STALIB=lib${LIBNAME}.a$/;" m |
| | | START cp_hal.h 41;" d |
| | | STOP cp_hal.h 42;" d |
| | | STRIP test/makefile /^export STRIP=${CROSS_COMPILE}strip$/;" m |
| | | SWE_TPDU test/swe_tpdud.h /^} SWE_TPDU;$/;" t typeref:struct:_SWE_TPDU |
| | | THREAD_BODY cp_proc.h /^typedef void *(THREAD_BODY) (void *thread_arg);$/;" t |
| | | TMP makefile /^TMP=$(shell echo $(ARCH) | tr "[A-Z]" "[a-z]")$/;" m |
| | | TMP test/makefile /^TMP=$(shell echo $(ARCH) | tr "[A-Z]" "[a-z]")$/;" m |
| | | TPDUD_PORT test/swe_tpdud.h 22;" d |
| | | TURN_ALL_LED at91_ioctl.h 61;" d |
| | | UID_LEN cp_ppp.h 27;" d |
| | | UPLINK_ADDR test/swe_tpdud.h 23;" d |
| | | UPLINK_PORT test/swe_tpdud.h 24;" d |
| | | VPATH makefile /^VPATH= .$/;" m |
| | | VPATH test/makefile /^VPATH= .$/;" m |
| | | YES cp_gprs.h 29;" d |
| | | ZIGBEE_RESET at91_ioctl.h 64;" d |
| | | ZIGBEE_STATUS at91_ioctl.h 65;" d |
| | | _CP_ARRAY cp_array.h /^typedef struct _CP_ARRAY$/;" s |
| | | _CP_COMPORT_H cp_comport.h 14;" d |
| | | _CP_DICTIONARY_H_ cp_dictionary.h 15;" d |
| | | _CP_FDS cp_fds.h /^struct _CP_FDS;$/;" x |
| | | _CP_FDS cp_fds.h /^typedef struct _CP_FDS$/;" s |
| | | _CP_FDS cp_sock.h /^struct _CP_FDS;$/;" x |
| | | _CP_INIPARSER_H_ cp_iniparser.h 11;" d |
| | | _CP_QNODE cp_queue.h /^typedef struct _CP_QNODE$/;" s |
| | | _CP_QUEUE cp_queue.h /^typedef struct _CP_QUEUE$/;" s |
| | | _CP_SOCK cp_fds.h /^struct _CP_SOCK;$/;" x |
| | | _CP_SOCK cp_sock.h /^struct _CP_SOCK;$/;" x |
| | | _CP_SOCK cp_sock.h /^typedef struct _CP_SOCK$/;" s |
| | | _CP_SOCK_CALLBACK cp_sock.h /^typedef struct _CP_SOCK_CALLBACK$/;" s |
| | | _CP_STRING_H cp_string.h 2;" d |
| | | _CP_VECTOR cp_vector.h /^typedef struct _CP_VECTOR$/;" s |
| | | _GPRS_LOCATION cp_atcmd.h /^typedef struct _GPRS_LOCATION$/;" s |
| | | _HARDWARE_INFO cp_atcmd.h /^typedef struct _HARDWARE_INFO$/;" s |
| | | _LINUX_LIST_H cp_klist.h 15;" d |
| | | _REGISTER_INFO cp_atcmd.h /^typedef struct _REGISTER_INFO$/;" s |
| | | _SWE_TPDU test/swe_tpdud.h /^typedef struct _SWE_TPDU$/;" s |
| | | __APN_ACCOUNT cp_ppp.h /^typedef struct __APN_ACCOUNT$/;" s |
| | | __AT91_IOCTL_H at91_ioctl.h 15;" d |
| | | __COM_PORT cp_comport.h /^typedef struct __COM_PORT$/;" s |
| | | __CP_ARRAY_H cp_array.h 15;" d |
| | | __CP_ATCMD_H cp_atcmd.h 15;" d |
| | | __CP_COMMON_H cp_common.h 15;" d |
| | | __CP_FDS_H cp_fds.h 15;" d |
| | | __CP_GPRS_H cp_gprs.h 15;" d |
| | | __CP_GSMMUX_H_ cp_gsmmux.h 16;" d |
| | | __CP_HAL_H cp_hal.h 14;" d |
| | | __CP_LOG_H cp_logger.h 15;" d |
| | | __CP_NETWORK_H cp_network.h 14;" d |
| | | __CP_PROC_H cp_proc.h 15;" d |
| | | __CP_PROC_SIG cp_proc.h /^typedef struct __CP_PROC_SIG$/;" s |
| | | __CP_QUEUE cp_queue.h 14;" d |
| | | __CP_RINGBUF_H_ cp_ringbuf.h 22;" d |
| | | __CP_SOCK_H cp_sock.h 14;" d |
| | | __CP_TIME_H cp_time.h 14;" d |
| | | __CP_VECTOR cp_vector.h 15;" d |
| | | __DATE_TIME cp_time.h /^typedef struct __DATE_TIME$/;" s |
| | | __MODULE_INFO cp_gprs.h /^typedef struct __MODULE_INFO$/;" s |
| | | __PPPD_INFO cp_ppp.h /^typedef struct __PPPD_INFO$/;" s |
| | | __PPP_CTX cp_ppp.h /^typedef struct __PPP_CTX$/;" s |
| | | __PPP_H cp_ppp.h 14;" d |
| | | __PPP_STAT cp_ppp.h /^typedef struct __PPP_STAT$/;" s |
| | | __SWE_TPDUD_H test/swe_tpdud.h 15;" d |
| | | __hlist_del cp_klist.h /^static inline void __hlist_del(struct hlist_node *n)$/;" f |
| | | __list_add cp_klist.h /^static inline void __list_add(struct list_head *new,$/;" f |
| | | __list_cut_position cp_klist.h /^static inline void __list_cut_position(struct list_head *list,$/;" f |
| | | __list_del cp_klist.h /^static inline void __list_del(struct list_head *prev, struct list_head *next)$/;" f |
| | | __list_for_each cp_klist.h 405;" d |
| | | __list_splice cp_klist.h /^static inline void __list_splice(const struct list_head *list,$/;" f |
| | | _cp_logger cp_logger.h /^typedef struct _cp_logger$/;" s |
| | | _cp_string cp_string.h /^typedef struct _cp_string$/;" s |
| | | _curOffset cp_logger.c /^ long _curOffset = ftell(logger->fp);$/;" l |
| | | _dictionary_ cp_dictionary.h /^typedef struct _dictionary_ {$/;" s |
| | | _line_status_ cp_iniparser.c /^typedef enum _line_status_ {$/;" g file: |
| | | _t_free cp_common.h /^static inline void _t_free(void *ptr$/;" f |
| | | _t_malloc cp_common.h /^static inline void *_t_malloc(size_t size$/;" f |
| | | acBuf cp_atcmd.c /^ char acBuf [256],$/;" l |
| | | acRecv cp_atcmd.c /^ char acRecv[1024];$/;" l |
| | | accept_cnt cp_sock.h /^ int accept_cnt; \/* current clients number, only listen socket use it*\/$/;" m struct:_CP_SOCK |
| | | accept_list cp_sock.h /^ struct list_head accept_list; \/* all the accept client list head, only listen socket use it *\/$/;" m struct:_CP_SOCK typeref:struct:_CP_SOCK::list_head |
| | | act cp_logger.c /^ struct sigaction act;$/;" l |
| | | actv_time cp_sock.h /^ unsigned long actv_time; \/* The last time get event(send\/recv) data in this socket *\/$/;" m struct:_CP_SOCK |
| | | adaption cp_gsmmux.h /^ unsigned int adaption;$/;" m struct:gsm_config |
| | | alloc_gsm_dataport cp_gprs.c /^COM_PORT *alloc_gsm_dataport(char *who, MODULE_INFO *module)$/;" f |
| | | ap cp_string.c /^ va_list ap;$/;" l |
| | | apn cp_ppp.h /^ APN_ACCOUNT apn; \/* PPP dial up APN *\/$/;" m struct:__PPP_CTX |
| | | apn cp_ppp.h /^ char apn[APN_LEN];$/;" m struct:__APN_ACCOUNT |
| | | arg cp_hal.c /^ int arg = led|(mode<<3);$/;" l |
| | | arg test/swe_tpdud.c /^ SWE_TPDU *arg = dlink->serv_sock->privt;$/;" l |
| | | argp cp_logger.c /^ va_list argp;$/;" l |
| | | args cp_proc.c /^ va_list args;$/;" l |
| | | array test/test_array.c /^ CP_ARRAY *array = NULL;$/;" l |
| | | at_match cp_atcmd.c /^unsigned char at_match (char *p_pcStr, char *p_pcMatch)$/;" f |
| | | atcmd cp_atcmd.c /^ char atcmd[64]={0}; $/;" l |
| | | atcmd cp_atcmd.c /^ char atcmd[64]={0};$/;" l |
| | | atcmd_check_at_ready cp_atcmd.c /^int atcmd_check_at_ready(COM_PORT *comport)$/;" f |
| | | atcmd_check_gprs_carrier cp_atcmd.c /^int atcmd_check_gprs_carrier(COM_PORT *comport, char *carrier)$/;" f |
| | | atcmd_check_gprs_iemi cp_atcmd.c /^int atcmd_check_gprs_iemi(COM_PORT *comport, char *iemi)$/;" f |
| | | atcmd_check_gprs_location cp_atcmd.c /^int atcmd_check_gprs_location(COM_PORT *comport, GPRS_LOCATION *loc)$/;" f |
| | | atcmd_check_gprs_mcc_mnc cp_atcmd.c /^int atcmd_check_gprs_mcc_mnc(COM_PORT *comport, char *mcc_mnc)$/;" f |
| | | atcmd_check_gprs_name cp_atcmd.c /^int atcmd_check_gprs_name(COM_PORT *comport, char *name)$/;" f |
| | | atcmd_check_gprs_network cp_atcmd.c /^int atcmd_check_gprs_network(COM_PORT *comport, int *network)$/;" f |
| | | atcmd_check_gprs_register cp_atcmd.c /^int atcmd_check_gprs_register(COM_PORT *comport)$/;" f |
| | | atcmd_check_gprs_signal cp_atcmd.c /^int atcmd_check_gprs_signal(COM_PORT *comport)$/;" f |
| | | atcmd_check_gprs_version cp_atcmd.c /^int atcmd_check_gprs_version(COM_PORT *comport, char *version)$/;" f |
| | | atcmd_check_hwinfo cp_gprs.c /^int atcmd_check_hwinfo(COM_PORT *comport, HW_INFO *hw, int times)$/;" f |
| | | atcmd_check_module_ready cp_gprs.c /^int atcmd_check_module_ready(COM_PORT *comport, int times)$/;" f |
| | | atcmd_check_network_info cp_gprs.c /^int atcmd_check_network_info(COM_PORT *comport, REGISTER_INFO *reg)$/;" f |
| | | atcmd_check_power_on cp_gprs.c /^int atcmd_check_power_on(COM_PORT *comport)$/;" f |
| | | atcmd_check_ready cp_gprs.c /^int atcmd_check_ready(MODULE_INFO *module)$/;" f |
| | | atcmd_check_regist cp_gprs.c /^int atcmd_check_regist(COM_PORT *comport, REGISTER_INFO *reg, int times)$/;" f |
| | | atcmd_check_sim_valid cp_atcmd.c /^int atcmd_check_sim_valid(COM_PORT *comport)$/;" f |
| | | atcmd_inspect_status cp_gprs.c /^int atcmd_inspect_status(MODULE_INFO *module)$/;" f |
| | | atcmd_module_preset cp_gprs.c /^int atcmd_module_preset(COM_PORT *comport)$/;" f |
| | | atcmd_set_apn cp_atcmd.c /^int atcmd_set_apn(COM_PORT *comport, char *apn)$/;" f |
| | | atcmd_set_network_mode cp_atcmd.c /^int atcmd_set_network_mode(COM_PORT *comport, int mode)$/;" f |
| | | attach_gsm0710 cp_gsmmux.c /^int attach_gsm0710(COM_PORT *comport)$/;" f |
| | | auth cp_ppp.h /^ char auth[10]; \/* PAP or CHAP *\/$/;" m struct:__APN_ACCOUNT |
| | | baudrate cp_comport.h /^ long baudrate;$/;" m struct:__COM_PORT |
| | | baudrate test/comport.c /^ int baudrate = 115200;$/;" l |
| | | buf cp_logger.c /^ char buf[MAX_LOG_MESSAGE_LEN];$/;" l |
| | | buf cp_network.c /^ char buf[512];$/;" l |
| | | buf cp_ppp.c /^ char buf[512];$/;" l |
| | | buf cp_ppp.c /^ char buf[512];$/;" l |
| | | buf cp_ppp.c /^ char buf[10];$/;" l |
| | | buf cp_string.c /^ char buf[CHUNK];$/;" l |
| | | buf test/comport.c /^ char buf[512];$/;" l |
| | | buf test/test_logger.c /^ char buf[30]="Hello World!\\n";$/;" l |
| | | buffer cp_ringbuf.h /^ u_char *buffer;$/;" m struct:ring_buffer |
| | | c cp_gsmmux.c /^ struct gsm_config c;$/;" l |
| | | c cp_iniparser.c /^ char * c ;$/;" l |
| | | c cp_logger.c /^ unsigned char c = buf[idx];$/;" l |
| | | c cp_string.c /^ unsigned char c = data[idx];$/;" l |
| | | c cp_string.c /^ unsigned char c = str->data[idx];$/;" l |
| | | cSleep cp_time.h /^ struct timespec cSleep;$/;" l |
| | | carrier cp_atcmd.h /^ char carrier[64];\/* Network operator *\/$/;" m struct:_REGISTER_INFO |
| | | cbfunc cp_sock.h /^ CP_SOCK_EVENT_CALLBACK cbfunc; \/* event callback function *\/$/;" m struct:_CP_SOCK |
| | | ch cp_string.c /^ char *i, *f, ch;$/;" l |
| | | check_and_rollback cp_logger.c /^static void check_and_rollback(void)$/;" f file: |
| | | check_daemon_running cp_proc.c /^int check_daemon_running(const char *pid_file)$/;" f |
| | | check_ppp_interface cp_ppp.c /^int check_ppp_interface(char *ppp_dev)$/;" f |
| | | check_ppp_ipaddr cp_ppp.c /^int check_ppp_ipaddr(PPPD_INFO *pppd_info, char *ppp_dev)$/;" f |
| | | check_ppp_stat cp_ppp.c /^int check_ppp_stat(PPP_STAT *ppp_stat, char *ppp_dev)$/;" f |
| | | check_pppd_pid cp_ppp.c /^int check_pppd_pid(char *find_key)$/;" f |
| | | clen cp_string.c /^ int clen = strlen(cstr);$/;" l |
| | | client_func cp_sock.h /^ CP_SOCK_EVENT_CALLBACK client_func; \/* client data callback function, only server socket use it *\/$/;" m struct:_CP_SOCK |
| | | client_list cp_fds.h /^ struct list_head client_list; \/* a list keep all the connect sockets *\/ $/;" m struct:_CP_FDS typeref:struct:_CP_FDS::list_head |
| | | close_gsm_dataport cp_gprs.c /^void close_gsm_dataport(MODULE_INFO *module)$/;" f |
| | | cmd cp_logger.c /^ char cmd[512];$/;" l |
| | | cmd cp_network.c /^ char cmd[256];$/;" l |
| | | cmd cp_ppp.c /^ char cmd[128];$/;" l |
| | | cmd cp_proc.c /^ char cmd[256];$/;" l |
| | | comport cp_comport.c /^ COM_PORT *comport = NULL;$/;" l |
| | | comport cp_gprs.c /^ COM_PORT *comport;$/;" l |
| | | comport cp_gprs.c /^ COM_PORT *comport = NULL;$/;" l |
| | | comport cp_gprs.h /^ COM_PORT *comport[MAX_DATAPORT]; \/* CMUX driver generate CMUX port *\/$/;" m struct:__MODULE_INFO |
| | | comport cp_ppp.h /^ COM_PORT *comport;$/;" m struct:__PPP_CTX |
| | | comport test/comport.c /^ COM_PORT *comport = NULL;$/;" l |
| | | comport test/test_hh.c /^ COM_PORT *comport = NULL;$/;" l |
| | | comport_close cp_comport.c /^void comport_close(COM_PORT * comport)$/;" f |
| | | comport_cnt cp_gprs.h /^ int comport_cnt; \/* GPRS data channel count *\/$/;" m struct:__MODULE_INFO |
| | | comport_init cp_comport.c /^COM_PORT *comport_init(const char *dev_name, int baudrate, const char *settings)$/;" f |
| | | comport_open cp_comport.c /^int comport_open(COM_PORT * comport)$/;" f |
| | | comport_recv cp_comport.c /^int comport_recv(COM_PORT * comport, char *buf, int buf_size, unsigned long timeout)$/;" f |
| | | comport_send cp_comport.c /^int comport_send(COM_PORT * comport, char *buf, int send_bytes)$/;" f |
| | | comport_term cp_comport.c /^void comport_term(COM_PORT * comport)$/;" f |
| | | container_of cp_common.h 25;" d |
| | | container_of cp_klist.h 29;" d |
| | | cp_add_epoll_event cp_fds.c /^int cp_add_epoll_event(CP_SOCK *sock)$/;" f |
| | | cp_array_add cp_array.c /^int cp_array_add(CP_ARRAY *array, void *data)$/;" f |
| | | cp_array_count cp_array.h 28;" d |
| | | cp_array_init cp_array.c /^CP_ARRAY *cp_array_init(CP_ARRAY *array, int size)$/;" f |
| | | cp_array_is_empty cp_array.h 27;" d |
| | | cp_array_is_full cp_array.h 26;" d |
| | | cp_array_rm_bydata cp_array.c /^int cp_array_rm_bydata(CP_ARRAY *array, void *data)$/;" f |
| | | cp_array_rm_byindex cp_array.c /^void cp_array_rm_byindex(CP_ARRAY *array, int index)$/;" f |
| | | cp_array_size cp_array.h 29;" d |
| | | cp_array_term cp_array.c /^void cp_array_term(CP_ARRAY *array)$/;" f |
| | | cp_array_travel cp_array.c /^void cp_array_travel(CP_ARRAY *array)$/;" f |
| | | cp_cstring_dump cp_string.c /^void cp_cstring_dump(char *data, int len)$/;" f |
| | | cp_del_epoll_event cp_fds.c /^void cp_del_epoll_event(CP_SOCK *sock)$/;" f |
| | | cp_dequeue cp_queue.c /^void *cp_dequeue(CP_QUEUE *queue)$/;" f |
| | | cp_enqueue cp_queue.c /^void *cp_enqueue(CP_QUEUE *queue, void *data)$/;" f |
| | | cp_fds_add_sock_registry cp_fds.c /^int cp_fds_add_sock_registry(CP_SOCK *sock)$/;" f |
| | | cp_fds_add_sock_task cp_fds.c /^int cp_fds_add_sock_task(CP_SOCK *sock)$/;" f |
| | | cp_fds_del_sock_registry cp_fds.c /^void cp_fds_del_sock_registry(CP_SOCK *sock)$/;" f |
| | | cp_fds_del_sock_task cp_fds.c /^void cp_fds_del_sock_task(CP_SOCK *sock)$/;" f |
| | | cp_fds_destroy_sock cp_fds.c /^void cp_fds_destroy_sock(CP_SOCK *sock)$/;" f |
| | | cp_fds_destroy_sock_clear cp_fds.h 99;" d |
| | | cp_fds_detect_event cp_fds.c /^int cp_fds_detect_event(CP_FDS *fds)$/;" f |
| | | cp_fds_init cp_fds.c /^CP_FDS *cp_fds_init(CP_FDS *fds, int maxevents, int timeout)$/;" f |
| | | cp_fds_list_sock_task cp_fds.c /^void cp_fds_list_sock_task(CP_FDS *fds)$/;" f |
| | | cp_fds_proc_event cp_fds.c /^void cp_fds_proc_event(CP_FDS *fds)$/;" f |
| | | cp_fds_setrlimit cp_fds.c /^int cp_fds_setrlimit(int maxfd)$/;" f |
| | | cp_fds_sock_dequeue cp_fds.c /^void *cp_fds_sock_dequeue(CP_FDS *fds)$/;" f |
| | | cp_fds_sock_enqueue cp_fds.c /^void *cp_fds_sock_enqueue(CP_SOCK *sock)$/;" f |
| | | cp_fds_sock_rmqueue cp_fds.c /^void *cp_fds_sock_rmqueue(CP_SOCK *sock)$/;" f |
| | | cp_fds_term cp_fds.c /^void cp_fds_term(CP_FDS *fds)$/;" f |
| | | cp_fds_term_clear cp_fds.h 71;" d |
| | | cp_hexdump_string cp_string.c /^const char *cp_hexdump_string(const void *data, size_t len)$/;" f |
| | | cp_install_proc_signal cp_proc.c /^void cp_install_proc_signal(void)$/;" f |
| | | cp_list_array_for_each cp_array.c /^ cp_list_array_for_each(array, i, data)$/;" f |
| | | cp_list_array_for_each cp_array.c /^ cp_list_array_for_each(array, i, entry)$/;" f |
| | | cp_list_array_for_each cp_array.h 31;" d |
| | | cp_list_array_for_each test/test_array.c /^ cp_list_array_for_each(array, i, sock)$/;" f |
| | | cp_log cp_logger.c /^void cp_log(int level, char *fmt, ...)$/;" f |
| | | cp_log_close cp_logger.c /^void cp_log_close(void)$/;" f |
| | | cp_log_default_signal_handler cp_logger.c /^static void cp_log_default_signal_handler(int sig)$/;" f file: |
| | | cp_log_dump cp_logger.c /^void cp_log_dump(int level, char *buf, int len)$/;" f |
| | | cp_log_init cp_logger.c /^cp_logger *cp_log_init(cp_logger *log, char *filename, int level, int log_size)$/;" f |
| | | cp_log_line cp_logger.c /^void cp_log_line(int level, char *file, int line, char *fmt, ...)$/;" f |
| | | cp_log_open cp_logger.c /^int cp_log_open(void)$/;" f |
| | | cp_log_raw cp_logger.c /^void cp_log_raw(const char *fmt, ...)$/;" f |
| | | cp_log_reopen cp_logger.c /^int cp_log_reopen(void)$/;" f |
| | | cp_log_set_time_format cp_logger.c /^void cp_log_set_time_format(char *time_format)$/;" f |
| | | cp_log_term cp_logger.c /^void cp_log_term(void)$/;" f |
| | | cp_logger cp_logger.h /^} cp_logger;$/;" t typeref:struct:_cp_logger |
| | | cp_mod_epoll_event cp_fds.c /^int cp_mod_epoll_event(CP_SOCK *sock, int event)$/;" f |
| | | cp_printout cp_logger.c /^static void cp_printout(char *level, char *fmt, va_list argp)$/;" f file: |
| | | cp_printout_line cp_logger.c /^static void cp_printout_line(char *level, char *fmt, char *file, int line, va_list argp)$/;" f file: |
| | | cp_proc_sighandler cp_proc.c /^void cp_proc_sighandler(int sig)$/;" f |
| | | cp_queue_count cp_queue.h 38;" d |
| | | cp_queue_destroy cp_queue.c /^void cp_queue_destroy(CP_QUEUE *queue)$/;" f |
| | | cp_queue_destroy_clear cp_queue.h 47;" d |
| | | cp_queue_init cp_queue.c /^CP_QUEUE *cp_queue_init(CP_QUEUE *queue, int size)$/;" f |
| | | cp_queue_is_empty cp_queue.h 37;" d |
| | | cp_queue_is_full cp_queue.h 36;" d |
| | | cp_queue_size cp_queue.h 39;" d |
| | | cp_rmqueue cp_queue.c /^void *cp_rmqueue(CP_QUEUE *queue, void *data)$/;" f |
| | | cp_sock_accept cp_sock.c /^int cp_sock_accept(CP_SOCK *serv_sock, CP_SOCK *new_sock)$/;" f |
| | | cp_sock_accept_regist cp_network.c /^int cp_sock_accept_regist(CP_SOCK *serv_sock)$/;" f |
| | | cp_sock_close cp_sock.c /^int cp_sock_close(CP_SOCK *sock)$/;" f |
| | | cp_sock_connect cp_sock.c /^int cp_sock_connect(CP_SOCK *sock, char *raddr, int rport, int lport)$/;" f |
| | | cp_sock_connect_regist cp_network.c /^CP_SOCK *cp_sock_connect_regist(CP_FDS *fds, CP_SOCK *sock, char *raddr, int rport, int lport, CP_SOCK_EVENT_CALLBACK service_route)$/;" f |
| | | cp_sock_detect_timeout cp_fds.c /^void cp_sock_detect_timeout(CP_FDS *fds)$/;" f |
| | | cp_sock_init cp_sock.c /^CP_SOCK *cp_sock_init(CP_SOCK *sock, unsigned int rsize, unsigned int ssize, int keepintvl, int keepcnt)$/;" f |
| | | cp_sock_listen cp_sock.c /^int cp_sock_listen(CP_SOCK *sock, char *laddr, int lport, int backlog)$/;" f |
| | | cp_sock_recv cp_sock.c /^int cp_sock_recv(CP_SOCK *sock)$/;" f |
| | | cp_sock_send cp_sock.c /^int cp_sock_send(CP_SOCK *sock)$/;" f |
| | | cp_sock_server_regist cp_network.c /^CP_SOCK *cp_sock_server_regist(CP_FDS *fds, char *addr, int port, int max_client, CP_SOCK_EVENT_CALLBACK service_route, void *data)$/;" f |
| | | cp_sock_set_buffer cp_sock.c /^int cp_sock_set_buffer(int sockfd, int rsize, int ssize)$/;" f |
| | | cp_sock_set_idle_timeout cp_sock.h /^static void inline cp_sock_set_idle_timeout(CP_SOCK *sock, unsigned long timeout)$/;" f |
| | | cp_sock_set_keepalive cp_sock.c /^int cp_sock_set_keepalive(int sockfd, int keepintvl, int keepcnt)$/;" f |
| | | cp_sock_set_msg_timeout cp_sock.h /^static void inline cp_sock_set_msg_timeout(CP_SOCK *sock, unsigned long timeout)$/;" f |
| | | cp_sock_set_nonblock cp_sock.c /^int cp_sock_set_nonblock(int sockfd)$/;" f |
| | | cp_sock_set_private_data cp_sock.h /^static void inline cp_sock_set_private_data(CP_SOCK *sock, void *data, PRIVT_FREE free)$/;" f |
| | | cp_sock_set_reuseaddr cp_sock.c /^int cp_sock_set_reuseaddr(int sockfd)$/;" f |
| | | cp_sock_term cp_sock.c /^void cp_sock_term(CP_SOCK *sock)$/;" f |
| | | cp_sock_term_all_client cp_fds.c /^void cp_sock_term_all_client(CP_FDS *fds)$/;" f |
| | | cp_sock_term_all_server cp_fds.c /^void cp_sock_term_all_server(CP_FDS *fds)$/;" f |
| | | cp_sock_term_all_service cp_network.c /^void cp_sock_term_all_service(CP_FDS *fds)$/;" f |
| | | cp_sock_term_all_service_clear cp_network.h 34;" d |
| | | cp_sock_term_all_task cp_fds.c /^void cp_sock_term_all_task(CP_FDS *fds)$/;" f |
| | | cp_sock_term_clear cp_sock.h 170;" d |
| | | cp_sock_term_server cp_fds.c /^void cp_sock_term_server(CP_SOCK *serv_sock)$/;" f |
| | | cp_string cp_string.h /^} cp_string;$/;" t typeref:struct:_cp_string |
| | | cp_string_append_char cp_string.c /^cp_string *cp_string_append_char(cp_string *str, char ch)$/;" f |
| | | cp_string_cat cp_string.c /^cp_string *cp_string_cat(cp_string *str, cp_string *appendum)$/;" f |
| | | cp_string_cat_bin cp_string.c /^cp_string *cp_string_cat_bin(cp_string *str, void *bin, int len)$/;" f |
| | | cp_string_clear_data cp_string.c /^void cp_string_clear_data(cp_string *str)$/;" f |
| | | cp_string_cmp cp_string.c /^int cp_string_cmp(cp_string *s1, cp_string *s2)$/;" f |
| | | cp_string_copy cp_string.c /^int cp_string_copy(cp_string *dst, cp_string *src)$/;" f |
| | | cp_string_create cp_string.c /^cp_string *cp_string_create(char *data, int len)$/;" f |
| | | cp_string_create_empty cp_string.c /^cp_string *cp_string_create_empty(int initial_size)$/;" f |
| | | cp_string_cstrcat cp_string.c /^cp_string *cp_string_cstrcat(cp_string *str, char *cstr)$/;" f |
| | | cp_string_cstrcopy cp_string.c /^int cp_string_cstrcopy(cp_string *dst, char *string, int len)$/;" f |
| | | cp_string_cstrcpy cp_string.c /^cp_string *cp_string_cstrcpy(cp_string *str, char *cstr)$/;" f |
| | | cp_string_cstrdup cp_string.c /^cp_string *cp_string_cstrdup(char *src)$/;" f |
| | | cp_string_data cp_string.c /^char *cp_string_data(cp_string *s)$/;" f |
| | | cp_string_destroy cp_string.c /^void cp_string_destroy(cp_string *str)$/;" f |
| | | cp_string_dump cp_string.c /^void cp_string_dump(cp_string *str)$/;" f |
| | | cp_string_dup cp_string.c /^cp_string *cp_string_dup(cp_string *src)$/;" f |
| | | cp_string_filter cp_string.c /^cp_string *cp_string_filter(cp_string *str, char *letters)$/;" f |
| | | cp_string_flip cp_string.c /^void cp_string_flip(cp_string *str)$/;" f |
| | | cp_string_len cp_string.c /^int cp_string_len(cp_string *s)$/;" f |
| | | cp_string_move cp_string.c /^int cp_string_move(cp_string *dst, cp_string *src)$/;" f |
| | | cp_string_read cp_string.c /^cp_string *cp_string_read(int fd, int len)$/;" f |
| | | cp_string_read_file cp_string.c /^cp_string *cp_string_read_file(char *filename)$/;" f |
| | | cp_string_tocstr cp_string.c /^char *cp_string_tocstr(cp_string *str)$/;" f |
| | | cp_string_write cp_string.c /^int cp_string_write(cp_string *str, int fd)$/;" f |
| | | cp_string_write_file cp_string.c /^int cp_string_write_file(cp_string *str, char *filename)$/;" f |
| | | cp_time_format cp_logger.c /^static char *cp_time_format = DEFAULT_TIME_FORMAT;$/;" v file: |
| | | cp_travel_queue cp_queue.c /^void cp_travel_queue(CP_QUEUE *queue)$/;" f |
| | | cp_vector_add cp_vector.c /^void *cp_vector_add(CP_VECTOR *vector, int index, void *item)$/;" f |
| | | cp_vector_count cp_vector.h 29;" d |
| | | cp_vector_del cp_vector.c /^void *cp_vector_del(CP_VECTOR *vector, int index)$/;" f |
| | | cp_vector_destroy cp_vector.c /^void cp_vector_destroy(CP_VECTOR *vector)$/;" f |
| | | cp_vector_get cp_vector.c /^void *cp_vector_get(CP_VECTOR *vector, int index)$/;" f |
| | | cp_vector_init cp_vector.c /^CP_VECTOR *cp_vector_init(int size)$/;" f |
| | | cp_vector_size cp_vector.h 30;" d |
| | | cstr cp_string.c /^ char *cstr = NULL;$/;" l |
| | | ctrl_thread_start cp_gprs.c /^void ctrl_thread_start(void *thread_arg)$/;" f |
| | | ctrl_thread_term cp_gprs.c /^void ctrl_thread_term(void *thread_arg)$/;" f |
| | | current cp_time.h /^ unsigned long current = time_now(); $/;" l |
| | | cval cp_dictionary.c /^ char cval[90] ;$/;" l |
| | | d cp_dictionary.c /^ dictionary * d ;$/;" l |
| | | d cp_string.c /^ unsigned char *d = (unsigned char *)data; $/;" l |
| | | daemonize cp_proc.c /^void daemonize(int nochdir, int noclose)$/;" f |
| | | data cp_array.c /^ void *data;$/;" l |
| | | data cp_array.h /^ void **data;$/;" m struct:_CP_ARRAY |
| | | data cp_string.h /^ char *data; \/**< internal buffer *\/$/;" m struct:_cp_string |
| | | databit cp_comport.h /^ unsigned char databit, parity, stopbit, flowctrl, is_connted;$/;" m struct:__COM_PORT |
| | | date cp_atcmd.h /^ char date[15];$/;" m struct:_GPRS_LOCATION |
| | | del_char_from_string cp_string.c /^char *del_char_from_string(char *str, char delchar)$/;" f |
| | | delay cp_atcmd.c /^ unsigned long delay = 200;$/;" l |
| | | delim cp_string.c /^ char delim[2]={*(fmt+2), '\\0'};$/;" l |
| | | dev cp_ppp.h /^ char dev[10]; \/* PPP dial up device name, such as PPP10 *\/$/;" m struct:__PPP_CTX |
| | | dev_name cp_comport.h /^ char dev_name[DEVNAME_LEN];$/;" m struct:__COM_PORT |
| | | dev_name test/comport.c /^ char *dev_name = NULL;$/;" l |
| | | devname cp_gprs.c /^ char devname[DEVNAME_LEN];$/;" l |
| | | dict cp_iniparser.c /^ dictionary * dict ;$/;" l |
| | | dictionary cp_dictionary.h /^} dictionary ;$/;" t typeref:struct:_dictionary_ |
| | | dictionary_del cp_dictionary.c /^void dictionary_del(dictionary * d)$/;" f |
| | | dictionary_dump cp_dictionary.c /^void dictionary_dump(dictionary * d, FILE * out)$/;" f |
| | | dictionary_get cp_dictionary.c /^char * dictionary_get(dictionary * d, const char * key, char * def)$/;" f |
| | | dictionary_hash cp_dictionary.c /^unsigned dictionary_hash(const char * key)$/;" f |
| | | dictionary_new cp_dictionary.c /^dictionary * dictionary_new(int size)$/;" f |
| | | dictionary_set cp_dictionary.c /^int dictionary_set(dictionary * d, const char * key, const char * val)$/;" f |
| | | dictionary_unset cp_dictionary.c /^void dictionary_unset(dictionary * d, const char * key)$/;" f |
| | | disp_mode test/comport.c /^ unsigned char disp_mode = 0x00;$/;" l |
| | | disp_settings cp_comport.c /^void disp_settings(COM_PORT * comport)$/;" f |
| | | dlink test/swe_tpdud.c /^ CP_SOCK *dlink = NULL;$/;" l |
| | | dlink test/swe_tpdud.c /^ CP_SOCK *dlink; $/;" l |
| | | dlink test/swe_tpdud.h /^ CP_SOCK *dlink; \/* listen port accept socket *\/$/;" m struct:_SWE_TPDU |
| | | do_ioctl test/comport.c /^int do_ioctl(char *dev_name, int cmd, int arg)$/;" f |
| | | done cp_proc.c /^ int done; $/;" l |
| | | dose cp_hal.c /^ int dose = 0;$/;" l |
| | | enable cp_ppp.h /^ unsigned char enable; \/* Enable PPP thread running or not, RFU *\/$/;" m struct:__PPP_CTX |
| | | encapsulation cp_gsmmux.h /^ unsigned int encapsulation;$/;" m struct:gsm_config |
| | | end cp_comport.c /^ char *ptr, *end;$/;" l |
| | | end cp_string.c /^ char *end = str;$/;" l |
| | | entry cp_array.c /^ void *entry;$/;" l |
| | | epfd cp_fds.h /^ int epfd; \/* the epoll_create() returns file description *\/ $/;" m struct:_CP_FDS |
| | | error cp_sock.h /^ CP_SOCK_EVENT_CALLBACK error;$/;" m struct:_CP_SOCK_CALLBACK |
| | | errs cp_iniparser.c /^ int errs=0;$/;" l |
| | | event cp_gprs.h /^ unsigned char event; \/* Request to set GPRS power REQ_POWER_ON, REQ_POWER_OFF or REQ_POWER_RESET *\/$/;" m struct:__MODULE_INFO |
| | | event cp_sock.h /^ struct epoll_event event; \/* epoll_wait returned event *\/$/;" m struct:_CP_SOCK typeref:struct:_CP_SOCK::epoll_event |
| | | event_cnt cp_fds.h /^ int event_cnt; \/* current socket regist in epoll *\/$/;" m struct:_CP_FDS |
| | | event_queue cp_fds.h /^ CP_QUEUE *event_queue; \/* a queue keep all these sockets get event happened *\/$/;" m struct:_CP_FDS |
| | | evts cp_fds.c /^ struct epoll_event evts[CP_MAX_EVENT_ONCE];$/;" l |
| | | exec_system_cmd cp_proc.c /^void exec_system_cmd(const char *format, ...)$/;" f |
| | | f cp_proc.c /^ FILE *f; $/;" l |
| | | f cp_string.c /^ char *i, *f, ch;$/;" l |
| | | f cp_string.c /^ char *f;$/;" l |
| | | fStatBuf cp_proc.c /^ struct stat fStatBuf; $/;" l |
| | | fStatBuf cp_proc.c /^ struct stat fStatBuf;$/;" l |
| | | fail_cnt cp_gprs.c /^ static int fail_cnt = 0;$/;" l file: |
| | | fail_cnt cp_ppp.h /^ unsigned char fail_cnt; \/* PPP failure count *\/$/;" m struct:__PPP_CTX |
| | | fd cp_comport.h /^ int fd;$/;" m struct:__COM_PORT |
| | | fd cp_hal.c /^ int fd = -1;$/;" l |
| | | fd cp_network.c /^ int fd; $/;" l |
| | | fd cp_ppp.c /^ int fd;$/;" l |
| | | fd cp_ppp.c /^ int fd = -1;$/;" l |
| | | fd cp_proc.c /^ int fd = -1; $/;" l |
| | | fd cp_proc.c /^ int retval, fd; $/;" l |
| | | fd cp_sock.c /^ int fd = -1;$/;" l |
| | | fd cp_sock.c /^ int fd = -1;$/;" l |
| | | fd cp_sock.h /^ int fd; \/* the socket file description *\/$/;" m struct:_CP_SOCK |
| | | fd cp_time.h /^ int rv, fd = -1;$/;" l |
| | | fd test/comport.c /^ int fd = -1;$/;" l |
| | | fds cp_comport.c /^ fd_set fds;$/;" l |
| | | fds cp_fds.c /^ CP_FDS *fds;$/;" l |
| | | fds cp_sock.h /^ struct _CP_FDS *fds; \/* epoll fds contex *\/$/;" m struct:_CP_SOCK typeref:struct:_CP_SOCK::_CP_FDS |
| | | fds test/swe_tpdud.c /^ CP_FDS *fds;$/;" l |
| | | fds test/test_sock_client.c /^ CP_FDS *fds;$/;" l |
| | | fds test/test_sock_server.c /^ CP_FDS *fds;$/;" l |
| | | file cp_logger.h /^ char file[FILENAME_LEN];$/;" m struct:_cp_logger |
| | | file test/test_logger.c /^ char file[FILENAME_LEN];$/;" l |
| | | filemode cp_logger.c /^ char *filemode;$/;" l |
| | | first cp_klist.h /^ struct hlist_node *first = h->first;$/;" l |
| | | first cp_klist.h /^ struct hlist_node *first;$/;" m struct:hlist_head typeref:struct:hlist_head::hlist_node |
| | | first cp_klist.h /^ struct list_head *first = list->next;$/;" l |
| | | flag cp_array.h /^ unsigned char flag;$/;" m struct:_CP_ARRAY |
| | | flag cp_fds.h /^ unsigned char flag; \/* Refer to follow definition *\/$/;" m struct:_CP_FDS |
| | | flag cp_logger.h /^ unsigned char flag; \/* This logger pointer is malloc() or passed by argument *\/$/;" m struct:_cp_logger |
| | | flag cp_sock.c /^ int flag;$/;" l |
| | | flag cp_sock.h /^ unsigned short flag; \/* Refer to the follow definition *\/$/;" m struct:_CP_SOCK |
| | | flag test/swe_tpdud.h /^ unsigned char flag;$/;" m struct:_SWE_TPDU |
| | | flowctrl cp_comport.h /^ unsigned char databit, parity, stopbit, flowctrl, is_connted;$/;" m struct:__COM_PORT |
| | | force cp_sock.c /^ int force = 0;$/;" l |
| | | found cp_iniparser.c /^ int found=0 ;$/;" l |
| | | foundsec cp_iniparser.c /^ int foundsec ;$/;" l |
| | | fp cp_logger.h /^ FILE *fp;$/;" m struct:_cp_logger |
| | | fp cp_network.c /^ FILE *fp;$/;" l |
| | | fp cp_ppp.c /^ FILE *fp;$/;" l |
| | | fp cp_ppp.c /^ FILE *fp = NULL;$/;" l |
| | | fp cp_string.c /^ FILE *fp = fopen(filename, "rb");$/;" l |
| | | fp cp_string.c /^ FILE *fp = fopen(filename, "wb");$/;" l |
| | | fp test/test_ini.c /^ FILE *fp;$/;" l |
| | | frag_size cp_comport.h /^ int frag_size;$/;" m struct:__COM_PORT |
| | | free_gsm_dataport cp_gprs.c /^void free_gsm_dataport(char *who, MODULE_INFO *module, COM_PORT **comport)$/;" f |
| | | front cp_queue.h /^ CP_QNODE *front;$/;" m struct:_CP_QUEUE |
| | | g_cp_signal cp_proc.c /^CP_PROC_SIG g_cp_signal={0};$/;" v |
| | | g_cp_signal cp_proc.h /^extern CP_PROC_SIG g_cp_signal;$/;" x |
| | | g_ucCtrlZ test/comport.c /^unsigned char g_ucCtrlZ;$/;" v |
| | | g_ucProcToken test/comport.c /^unsigned char g_ucProcToken = 0x01;$/;" v |
| | | gap cp_atcmd.c /^ unsigned long gap = 300;$/;" l |
| | | get_apn_conf cp_ppp.c /^int get_apn_conf(char *ini_name, char *ini_key, APN_ACCOUNT *apn, unsigned char type)$/;" f |
| | | get_current_time cp_time.h /^static inline void get_current_time(DATE_TIME * date)$/;" f |
| | | get_daemon_pid cp_proc.c /^pid_t get_daemon_pid(const char *pid_file)$/;" f |
| | | get_rtc_time cp_time.h /^static inline int get_rtc_time(DATE_TIME *date)$/;" f |
| | | get_sys_time cp_time.h 94;" d |
| | | gsm_config cp_gsmmux.h /^struct gsm_config$/;" s |
| | | gsmport cp_gprs.h /^ COM_PORT *gsmport; \/* The GSM hardware UART port *\/$/;" m struct:__MODULE_INFO |
| | | hal_get_gmtube_dose cp_hal.c /^int hal_get_gmtube_dose(void)$/;" f |
| | | hal_get_gprs_power cp_hal.c /^int hal_get_gprs_power(void)$/;" f |
| | | hal_get_gps_power cp_hal.c /^int hal_get_gps_power(void)$/;" f |
| | | hal_get_zigbee_status cp_hal.c /^int hal_get_zigbee_status(void)$/;" f |
| | | hal_reset_zigbee cp_hal.c /^int hal_reset_zigbee(void)$/;" f |
| | | hal_set_gmtube cp_hal.c /^int hal_set_gmtube(status)$/;" f |
| | | hal_turn_gprs_power cp_hal.c /^int hal_turn_gprs_power(int status)$/;" f |
| | | hal_turn_gps_power cp_hal.c /^int hal_turn_gps_power(int status)$/;" f |
| | | hal_turn_led_blink cp_hal.c /^int hal_turn_led_blink(int led, int mode)$/;" f |
| | | hal_turn_led_off cp_hal.c /^int hal_turn_led_off(int led)$/;" f |
| | | hal_turn_led_on cp_hal.c /^int hal_turn_led_on(int led)$/;" f |
| | | hash cp_dictionary.c /^ unsigned hash ;$/;" l |
| | | hash cp_dictionary.h /^ unsigned * hash ; \/** List of hash values for keys *\/$/;" m struct:_dictionary_ |
| | | hc cp_logger.c /^ char hc[4];$/;" l |
| | | hc cp_string.c /^ char hc[4];$/;" l |
| | | hints cp_sock.c /^ struct addrinfo hints, *rp;$/;" l |
| | | hlist_add_after cp_klist.h /^static inline void hlist_add_after(struct hlist_node *n,$/;" f |
| | | hlist_add_before cp_klist.h /^static inline void hlist_add_before(struct hlist_node *n,$/;" f |
| | | hlist_add_head cp_klist.h /^static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)$/;" f |
| | | hlist_del cp_klist.h /^static inline void hlist_del(struct hlist_node *n)$/;" f |
| | | hlist_del_init cp_klist.h /^static inline void hlist_del_init(struct hlist_node *n)$/;" f |
| | | hlist_empty cp_klist.h /^static inline int hlist_empty(const struct hlist_head *h)$/;" f |
| | | hlist_entry cp_klist.h 660;" d |
| | | hlist_for_each cp_klist.h 662;" d |
| | | hlist_for_each_entry cp_klist.h 677;" d |
| | | hlist_for_each_entry_continue cp_klist.h 689;" d |
| | | hlist_for_each_entry_from cp_klist.h 701;" d |
| | | hlist_for_each_entry_safe cp_klist.h 714;" d |
| | | hlist_for_each_safe cp_klist.h 666;" d |
| | | hlist_head cp_klist.h /^struct hlist_head {$/;" s |
| | | hlist_node cp_klist.h /^struct hlist_node {$/;" s |
| | | hlist_unhashed cp_klist.h /^static inline int hlist_unhashed(const struct hlist_node *h)$/;" f |
| | | hw cp_gprs.h /^ HW_INFO hw; \/* GPRS Hardware information *\/$/;" m struct:__MODULE_INFO |
| | | i cp_array.c /^ int i, rv = -3;$/;" l |
| | | i cp_array.c /^ int i;$/;" l |
| | | i cp_array.c /^ int i;$/;" l |
| | | i cp_atcmd.c /^ int i = 0;$/;" l |
| | | i cp_atcmd.c /^ int i = 0;$/;" l |
| | | i cp_dictionary.c /^ int i ;$/;" l |
| | | i cp_dictionary.c /^ int i ;$/;" l |
| | | i cp_fds.c /^ int i;$/;" l |
| | | i cp_fds.c /^ int i=0, nfds=0;$/;" l |
| | | i cp_fds.c /^ int i;$/;" l |
| | | i cp_gprs.c /^ int i=0;$/;" l |
| | | i cp_gprs.c /^ int i=0;$/;" l |
| | | i cp_gprs.c /^ int i;$/;" l |
| | | i cp_gprs.c /^ int i, rv = 0;$/;" l |
| | | i cp_gprs.c /^ int i;$/;" l |
| | | i cp_gprs.c /^ int i, retval = -1;$/;" l |
| | | i cp_gsmmux.h /^ unsigned int i;$/;" m struct:gsm_config |
| | | i cp_iniparser.c /^ int i ;$/;" l |
| | | i cp_iniparser.c /^ int i ;$/;" l |
| | | i cp_iniparser.c /^ int i, j ;$/;" l |
| | | i cp_proc.c /^ int i; $/;" l |
| | | i cp_ringbuf.c /^ int i;$/;" l |
| | | i cp_string.c /^ char *i, *f, ch;$/;" l |
| | | i cp_string.c /^ char *i;$/;" l |
| | | i cp_string.c /^ unsigned int i, left;$/;" l |
| | | i test/comport.c /^ int i;$/;" l |
| | | i test/test_array.c /^ int i;$/;" l |
| | | i test/test_hh.c /^ int i;$/;" l |
| | | i test/test_klist.c /^ int i;$/;" l |
| | | i test/test_queue.c /^ int i;$/;" l |
| | | i test/test_string.c /^ int i;$/;" l |
| | | i test/test_vector.c /^ int i, n;$/;" l |
| | | iCmdLen cp_atcmd.c /^ int iCmdLen = 0,$/;" l |
| | | iDay cp_time.h /^ int iDay;$/;" m struct:__DATE_TIME |
| | | iDayOfWeek cp_time.h /^ int iDayOfWeek;$/;" m struct:__DATE_TIME |
| | | iHour cp_time.h /^ int iHour;$/;" m struct:__DATE_TIME |
| | | iMinute cp_time.h /^ int iMinute;$/;" m struct:__DATE_TIME |
| | | iMonth cp_time.h /^ int iMonth;$/;" m struct:__DATE_TIME |
| | | iPtr cp_string.c /^ int *iPtr;$/;" l |
| | | iRecvLen cp_atcmd.c /^ iRecvLen = 0,$/;" l |
| | | iRecvSize cp_atcmd.c /^ iRecvSize = 0,$/;" l |
| | | iRet cp_comport.c /^ int iRet;$/;" l |
| | | iSecond cp_time.h /^ int iSecond;$/;" m struct:__DATE_TIME |
| | | iSize cp_atcmd.c /^ iSize = 0;$/;" l |
| | | iYear cp_time.h /^ int iYear;$/;" m struct:__DATE_TIME |
| | | idle_timeout cp_sock.h /^ unsigned long idle_timeout; \/* this is set to the socket idle timeout value, when timeout will disconnect *\/$/;" m struct:_CP_SOCK |
| | | idx cp_logger.c /^ int idx;$/;" l |
| | | idx cp_string.c /^ int idx;$/;" l |
| | | idx cp_string.c /^ char *idx = str;$/;" l |
| | | iemi cp_atcmd.h /^ char iemi[64]; \/* AT+CGSN check GPRS module IEMI(International Mobile station Equipment Identity) number *\/$/;" m struct:_HARDWARE_INFO |
| | | ifr cp_network.c /^ struct ifreq ifr; $/;" l |
| | | ifr cp_ppp.c /^ struct ifreq ifr;$/;" l |
| | | in cp_iniparser.c /^ FILE * in ;$/;" l |
| | | inaddr cp_sock.c /^ struct in_addr inaddr;$/;" l |
| | | index cp_sock.h /^ int index; \/* The index member position in the task array *\/$/;" m struct:_CP_SOCK |
| | | ini cp_ppp.c /^ dictionary *ini ;$/;" l |
| | | ini test/test_ini.c /^ dictionary *ini;$/;" l |
| | | iniparser_dump cp_iniparser.c /^void iniparser_dump(dictionary * d, FILE * f)$/;" f |
| | | iniparser_dump_ini cp_iniparser.c /^void iniparser_dump_ini(dictionary * d, FILE * f)$/;" f |
| | | iniparser_dumpsection_ini cp_iniparser.c /^void iniparser_dumpsection_ini(dictionary * d, char * s, FILE * f)$/;" f |
| | | iniparser_find_entry cp_iniparser.c /^int iniparser_find_entry($/;" f |
| | | iniparser_freedict cp_iniparser.c /^void iniparser_freedict(dictionary * d)$/;" f |
| | | iniparser_getboolean cp_iniparser.c /^int iniparser_getboolean(dictionary * d, const char * key, int notfound)$/;" f |
| | | iniparser_getdouble cp_iniparser.c /^double iniparser_getdouble(dictionary * d, const char * key, double notfound)$/;" f |
| | | iniparser_getint cp_iniparser.c /^int iniparser_getint(dictionary * d, const char * key, int notfound)$/;" f |
| | | iniparser_getlong cp_iniparser.c /^int iniparser_getlong(dictionary * d, const char * key, int notfound)$/;" f |
| | | iniparser_getnsec cp_iniparser.c /^int iniparser_getnsec(dictionary * d)$/;" f |
| | | iniparser_getseckeys cp_iniparser.c /^char ** iniparser_getseckeys(dictionary * d, char * s)$/;" f |
| | | iniparser_getsecname cp_iniparser.c /^char * iniparser_getsecname(dictionary * d, int n)$/;" f |
| | | iniparser_getsecnkeys cp_iniparser.c /^int iniparser_getsecnkeys(dictionary * d, char * s)$/;" f |
| | | iniparser_getstring cp_iniparser.c /^char * iniparser_getstring(dictionary * d, const char * key, char * def)$/;" f |
| | | iniparser_line cp_iniparser.c /^static line_status iniparser_line($/;" f file: |
| | | iniparser_load cp_iniparser.c /^dictionary * iniparser_load(const char * ininame)$/;" f |
| | | iniparser_set cp_iniparser.c /^int iniparser_set(dictionary * ini, const char * entry, const char * val)$/;" f |
| | | iniparser_unset cp_iniparser.c /^void iniparser_unset(dictionary * ini, const char * entry)$/;" f |
| | | init_gsm_module cp_gprs.c /^int init_gsm_module(MODULE_INFO *module)$/;" f |
| | | initiator cp_gsmmux.h /^ unsigned int initiator;$/;" m struct:gsm_config |
| | | inspect_network_status cp_ppp.c /^int inspect_network_status(PPP_CTX *ppp_ctx)$/;" f |
| | | ipc_dir cp_proc.c /^ char ipc_dir[64] = { 0 }; $/;" l |
| | | is_connted cp_comport.h /^ unsigned char databit, parity, stopbit, flowctrl, is_connted;$/;" m struct:__COM_PORT |
| | | item cp_queue.c /^ void *item;$/;" l |
| | | item cp_queue.h /^ void *item;$/;" m struct:_CP_QNODE |
| | | items cp_array.h /^ int items;$/;" m struct:_CP_ARRAY |
| | | items cp_queue.h /^ int items;$/;" m struct:_CP_QUEUE |
| | | j cp_iniparser.c /^ int j ;$/;" l |
| | | j cp_iniparser.c /^ int i, j ;$/;" l |
| | | j cp_iniparser.c /^ int j ;$/;" l |
| | | k cp_gsmmux.h /^ unsigned int k;$/;" m struct:gsm_config |
| | | kbhit cp_comport.c /^int kbhit()$/;" f |
| | | keepcnt cp_sock.h /^ int keepcnt; \/* heartbeat(keepalive) count *\/$/;" m struct:_CP_SOCK |
| | | keepintvl cp_sock.h /^ int keepintvl; \/* heartbeat(keepalive) detect interval *\/$/;" m struct:_CP_SOCK |
| | | key cp_dictionary.h /^ char ** key ; \/** List of string keys *\/$/;" m struct:_dictionary_ |
| | | key cp_iniparser.c /^ char key [ASCIILINESZ+1] ;$/;" l |
| | | keym cp_iniparser.c /^ char keym[ASCIILINESZ+1];$/;" l |
| | | keys cp_iniparser.c /^ char **keys;$/;" l |
| | | kill_pppd_process cp_ppp.c /^int kill_pppd_process(COM_PORT *comport)$/;" f |
| | | l cp_iniparser.c /^ static char l[ASCIILINESZ+1];$/;" l file: |
| | | lPtr cp_string.c /^ long *lPtr;$/;" l |
| | | laddr cp_sock.h /^ char laddr[16]; \/* local IP address*\/$/;" m struct:_CP_SOCK |
| | | last cp_iniparser.c /^ char * last ;$/;" l |
| | | last cp_iniparser.c /^ int last=0 ;$/;" l |
| | | last cp_klist.h /^ struct list_head *last = list->prev;$/;" l |
| | | last_rx_bytes cp_ppp.c /^ unsigned long long last_rx_bytes= ppp_stat->ullRx_Bytes;$/;" l |
| | | last_tx_bytes cp_ppp.c /^ unsigned long long last_tx_bytes= ppp_stat->ullTx_Bytes;$/;" l |
| | | latitude cp_atcmd.h /^ char latitude[15];$/;" m struct:_GPRS_LOCATION |
| | | lc_key cp_iniparser.c /^ char * lc_key ;$/;" l |
| | | ldisc cp_gsmmux.c /^ int ldisc = N_GSM0710;$/;" l |
| | | ldx cp_logger.c /^ int ldx = idx % CHARS_PER_LINE;$/;" l |
| | | left cp_sock.c /^ int rv, left;$/;" l |
| | | left cp_string.c /^ int left;$/;" l |
| | | left cp_string.c /^ unsigned int i, left;$/;" l |
| | | left_line cp_iniparser.c /^ static char left_line[ASCIILINESZ+1];$/;" l file: |
| | | len cp_dictionary.c /^ int len ;$/;" l |
| | | len cp_iniparser.c /^ int len, offset ;$/;" l |
| | | len cp_iniparser.c /^ int len ;$/;" l |
| | | len cp_sock.c /^ int len = sizeof(saddr); $/;" l |
| | | len cp_sock.c /^ int len = sizeof (int);$/;" l |
| | | len cp_sock.c /^ socklen_t len = sizeof(saddr);$/;" l |
| | | len cp_string.c /^ int len = str->len;$/;" l |
| | | len cp_string.h /^ int len; \/**< size used *\/$/;" m struct:_cp_string |
| | | level cp_logger.h /^ int level;$/;" m struct:_cp_logger |
| | | line cp_iniparser.c /^ char line[ASCIILINESZ+1];$/;" l |
| | | line cp_iniparser.c /^ char line [ASCIILINESZ+1] ;$/;" l |
| | | line_done cp_logger.c /^ short line_done = 1;$/;" l |
| | | line_done cp_string.c /^ short line_done = 1;$/;" l |
| | | line_status cp_iniparser.c /^} line_status ;$/;" t typeref:enum:_line_status_ file: |
| | | lineno cp_iniparser.c /^ int lineno=0 ;$/;" l |
| | | list_add cp_klist.h /^static inline void list_add(struct list_head *new, struct list_head *head)$/;" f |
| | | list_add_tail cp_klist.h /^static inline void list_add_tail(struct list_head *new, struct list_head *head)$/;" f |
| | | list_cut_position cp_klist.h /^static inline void list_cut_position(struct list_head *list,$/;" f |
| | | list_del cp_klist.h /^static inline void list_del(struct list_head *entry)$/;" f |
| | | list_del_init cp_klist.h /^static inline void list_del_init(struct list_head *entry)$/;" f |
| | | list_empty cp_klist.h /^static inline int list_empty(const struct list_head *head)$/;" f |
| | | list_empty_careful cp_klist.h /^static inline int list_empty_careful(const struct list_head *head)$/;" f |
| | | list_entry cp_klist.h 372;" d |
| | | list_first_entry cp_klist.h 383;" d |
| | | list_for_each cp_klist.h 391;" d |
| | | list_for_each_entry cp_klist.h 444;" d |
| | | list_for_each_entry_continue cp_klist.h 480;" d |
| | | list_for_each_entry_continue_reverse cp_klist.h 494;" d |
| | | list_for_each_entry_from cp_klist.h 507;" d |
| | | list_for_each_entry_reverse cp_klist.h 455;" d |
| | | list_for_each_entry_safe cp_klist.h 518;" d |
| | | list_for_each_entry_safe test/test_klist.c /^ list_for_each_entry_safe(sock, tsock, head, rlist)$/;" f |
| | | list_for_each_entry_safe_continue cp_klist.h 534;" d |
| | | list_for_each_entry_safe_from cp_klist.h 550;" d |
| | | list_for_each_entry_safe_reverse cp_klist.h 565;" d |
| | | list_for_each_prev cp_klist.h 413;" d |
| | | list_for_each_prev_safe cp_klist.h 433;" d |
| | | list_for_each_safe cp_klist.h 423;" d |
| | | list_head cp_klist.h /^struct list_head {$/;" s |
| | | list_is_last cp_klist.h /^static inline int list_is_last(const struct list_head *list,$/;" f |
| | | list_is_singular cp_klist.h /^static inline int list_is_singular(const struct list_head *head)$/;" f |
| | | list_move cp_klist.h /^static inline void list_move(struct list_head *list, struct list_head *head)$/;" f |
| | | list_move_tail cp_klist.h /^static inline void list_move_tail(struct list_head *list,$/;" f |
| | | list_prepare_entry cp_klist.h 468;" d |
| | | list_replace cp_klist.h /^static inline void list_replace(struct list_head *old,$/;" f |
| | | list_replace_init cp_klist.h /^static inline void list_replace_init(struct list_head *old,$/;" f |
| | | list_splice cp_klist.h /^static inline void list_splice(const struct list_head *list,$/;" f |
| | | list_splice_init cp_klist.h /^static inline void list_splice_init(struct list_head *list,$/;" f |
| | | list_splice_tail cp_klist.h /^static inline void list_splice_tail(struct list_head *list,$/;" f |
| | | list_splice_tail_init cp_klist.h /^static inline void list_splice_tail_init(struct list_head *list,$/;" f |
| | | lit cp_logger.c /^ char lit[CHARS_PER_LINE + 2];$/;" l |
| | | lit cp_string.c /^ char lit[CHARS_PER_LINE + 1];$/;" l |
| | | loc cp_atcmd.h /^ GPRS_LOCATION loc; \/* Location *\/$/;" m struct:_REGISTER_INFO |
| | | local cp_logger.c /^ struct tm *local;$/;" l |
| | | lock cp_gprs.c /^ static int lock = 0;$/;" l file: |
| | | lock cp_gprs.h /^ pthread_mutex_t lock; \/* Module control mutex lock *\/$/;" m struct:__MODULE_INFO |
| | | log cp_atcmd.c /^ char log[512] = {0};$/;" l |
| | | log_banner cp_logger.c /^static void log_banner(char *prefix)$/;" f file: |
| | | log_dbg cp_logger.h 102;" d |
| | | log_dbg cp_logger.h 94;" d |
| | | log_err cp_logger.h 105;" d |
| | | log_err cp_logger.h 97;" d |
| | | log_fatal cp_logger.h 106;" d |
| | | log_fatal cp_logger.h 98;" d |
| | | log_info cp_logger.h 101;" d |
| | | log_info cp_logger.h 93;" d |
| | | log_nrml cp_logger.h 103;" d |
| | | log_nrml cp_logger.h 95;" d |
| | | log_rollback_size cp_logger.c /^static unsigned long log_rollback_size = LOG_ROLLBACK_NONE;$/;" v file: |
| | | log_str cp_logger.c /^char *log_str[LOG_LEVEL_MAX + 1] = { "", "F", "E", "W", "N", "D", "I", "T", "M" };$/;" v |
| | | log_str cp_logger.h /^extern char *log_str[];$/;" x |
| | | log_trace cp_logger.h 100;" d |
| | | log_trace cp_logger.h 92;" d |
| | | log_warn cp_logger.h 104;" d |
| | | log_warn cp_logger.h 96;" d |
| | | logger cp_logger.c /^static cp_logger *logger = NULL;$/;" v file: |
| | | loglevel test/swe_tpdud.c /^ int loglevel = LOG_LEVEL_NRML;$/;" l |
| | | long_options test/comport.c /^ struct option long_options[] = {$/;" l |
| | | long_options test/swe_tpdud.c /^ struct option long_options[] = $/;" l |
| | | long_options test/test_hal.c /^ struct option long_options[] = {$/;" l |
| | | longitude cp_atcmd.h /^ char longitude[15];$/;" m struct:_GPRS_LOCATION |
| | | lost_percent cp_network.c /^ int lost_percent = 100;$/;" l |
| | | lost_percent cp_ppp.c /^ int lost_percent;$/;" l |
| | | lport cp_sock.h /^ int lport; \/* local port *\/$/;" m struct:_CP_SOCK |
| | | lport test/swe_tpdud.h /^ int lport; \/* dlink local listen port *\/$/;" m struct:_SWE_TPDU |
| | | main cp_dictionary.c /^int main(int argc, char *argv[])$/;" f |
| | | main test/comport.c /^int main(int argc, char **argv)$/;" f |
| | | main test/swe_tpdud.c /^int main (int argc, char **argv)$/;" f |
| | | main test/test_array.c /^int main (int argc, char **argv)$/;" f |
| | | main test/test_hal.c /^int main (int argc, char **argv)$/;" f |
| | | main test/test_hh.c /^int main (int argc, char **argv)$/;" f |
| | | main test/test_ini.c /^int main (int argc, char **argv)$/;" f |
| | | main test/test_klist.c /^int main (int argc, char **argv)$/;" f |
| | | main test/test_logger.c /^int main (int argc, char **argv)$/;" f |
| | | main test/test_queue.c /^int main (int argc, char **argv)$/;" f |
| | | main test/test_sock_client.c /^int main (int argc, char **argv)$/;" f |
| | | main test/test_sock_server.c /^int main (int argc, char **argv)$/;" f |
| | | main test/test_string.c /^int main (int argc, char **argv)$/;" f |
| | | main test/test_vector.c /^int main (int argc, char **argv)$/;" f |
| | | max_client cp_sock.h /^ int max_client; \/* max clients, only listen socket use it*\/$/;" m struct:_CP_SOCK |
| | | max_event cp_fds.h /^ int max_event; \/* Maximum monitor FD number *\/$/;" m struct:_CP_FDS |
| | | mcc cp_atcmd.c /^ char mcc[5];$/;" l |
| | | mcc_mnc cp_atcmd.h /^ char mcc_mnc[16];\/* Mobile Country Code, China is 460 *\/$/;" m struct:_GPRS_LOCATION |
| | | mem cp_vector.h /^ void **mem;$/;" m struct:_CP_VECTOR |
| | | mem_double cp_dictionary.c /^static void * mem_double(void * ptr, int size)$/;" f file: |
| | | micro_second_sleep cp_time.h /^static inline void micro_second_sleep(unsigned long ms)$/;" f |
| | | mnc cp_atcmd.c /^ char mnc[5];$/;" l |
| | | mode cp_proc.c /^ int mode = S_IROTH | S_IXOTH | S_IRGRP | S_IXGRP | S_IRWXU;$/;" l |
| | | mode cp_sock.h /^ int mode; \/* socket work mode: listen, accept, connect *\/$/;" m struct:_CP_SOCK |
| | | model cp_atcmd.h /^ char model[64]; \/* AT+CGMM check GPRS module model *\/$/;" m struct:_HARDWARE_INFO |
| | | module cp_gprs.c /^ MODULE_INFO *module = (MODULE_INFO *)thread_arg;$/;" l |
| | | module cp_ppp.c /^ MODULE_INFO *module = ppp_ctx->module; $/;" l |
| | | module cp_ppp.c /^ MODULE_INFO *module;$/;" l |
| | | module cp_ppp.h /^ MODULE_INFO *module;$/;" m struct:__PPP_CTX |
| | | mrev cp_atcmd.h /^ char mrev[64]; \/* AT+CGMR check GPRS module revision *\/$/;" m struct:_HARDWARE_INFO |
| | | mru cp_gsmmux.h /^ unsigned int mru;$/;" m struct:gsm_config |
| | | msg_time cp_sock.h /^ unsigned long msg_time; \/* The last time get incoming data in this socket *\/$/;" m struct:_CP_SOCK |
| | | msg_timeout cp_sock.h /^ unsigned long msg_timeout; \/* this is set to the socket recv data timeout value, *\/$/;" m struct:_CP_SOCK |
| | | mtu cp_gsmmux.h /^ unsigned int mtu;$/;" m struct:gsm_config |
| | | n cp_dictionary.h /^ int n ; \/** Number of entries in dictionary *\/$/;" m struct:_dictionary_ |
| | | n test/test_vector.c /^ int i, n;$/;" l |
| | | n2 cp_gsmmux.h /^ unsigned int n2;$/;" m struct:gsm_config |
| | | netaddr cp_ppp.h /^ char netaddr[INET_ADDRSTRLEN];$/;" m struct:__PPPD_INFO |
| | | network cp_ppp.h /^ unsigned char network; \/* PPP network status: PPP_FAIL,PPP_BAD,PPP_GOOD *\/$/;" m struct:__PPP_CTX |
| | | network_ping_test cp_network.c /^int network_ping_test(char *from, char *ping_ip)$/;" f |
| | | new_cfg cp_comport.c /^ struct termios old_cfg, new_cfg;$/;" l |
| | | new_first cp_klist.h /^ struct list_head *new_first = entry->next;$/;" l |
| | | new_sock cp_network.c /^ CP_SOCK *new_sock = NULL;$/;" l |
| | | newptr cp_dictionary.c /^ void * newptr ;$/;" l |
| | | next cp_klist.h /^ struct hlist_node *next = n->next;$/;" l |
| | | next cp_klist.h /^ struct hlist_node *next, **pprev;$/;" m struct:hlist_node typeref:struct:hlist_node::hlist_node |
| | | next cp_klist.h /^ struct list_head *next = head->next;$/;" l |
| | | next cp_klist.h /^ struct list_head *next, *prev;$/;" m struct:list_head typeref:struct:list_head::list_head |
| | | next cp_queue.h /^ struct _CP_QNODE *next;$/;" m struct:_CP_QNODE typeref:struct:_CP_QNODE::_CP_QNODE |
| | | nfds cp_fds.c /^ int i=0, nfds=0;$/;" l |
| | | nic_get_ipaddr cp_network.c /^int nic_get_ipaddr(char *nic, char *ipaddr)$/;" f |
| | | nic_get_ptpaddr cp_network.c /^int nic_get_ptpaddr(char *nic, char *ptpaddr)$/;" f |
| | | nic_network_config cp_network.c /^int nic_network_config(char *nic, char *mac, char *ip)$/;" f |
| | | nkeys cp_iniparser.c /^ int seclen, nkeys ;$/;" l |
| | | node cp_queue.c /^ CP_QNODE *node;$/;" l |
| | | node cp_queue.c /^ CP_QNODE *node, *tmp;$/;" l |
| | | node cp_queue.c /^ CP_QNODE *node;$/;" l |
| | | nonblock cp_comport.c /^void nonblock()$/;" f |
| | | now cp_logger.c /^ struct timeval now;$/;" l |
| | | now cp_time.h /^ struct timeval now; $/;" l |
| | | now cp_time.h /^ time_t now = time(NULL);$/;" l |
| | | nsec cp_iniparser.c /^ int nsec ;$/;" l |
| | | nsec cp_iniparser.c /^ int nsec ;$/;" l |
| | | offset cp_iniparser.c /^ int len, offset ;$/;" l |
| | | offsetof cp_common.h 22;" d |
| | | offsetof cp_klist.h 27;" d |
| | | offsetof cp_klist.h 28;" d |
| | | old_cfg cp_comport.c /^ struct termios old_cfg, new_cfg;$/;" l |
| | | old_flags cp_comport.c /^ int old_flags;$/;" l |
| | | olen cp_string.c /^ int olen = str->len;$/;" l |
| | | open_gsm_dataport cp_gprs.c /^int open_gsm_dataport(MODULE_INFO *module)$/;" f |
| | | opt cp_sock.c /^ int opt;$/;" l |
| | | opt cp_sock.c /^ int opt;$/;" l |
| | | opt cp_sock.c /^ int opt = 1;$/;" l |
| | | opt test/comport.c /^ int opt = 0;$/;" l |
| | | opt test/swe_tpdud.c /^ int opt;$/;" l |
| | | opt test/test_hal.c /^ int opt;$/;" l |
| | | optlen cp_sock.c /^ socklen_t optlen = sizeof(opt);$/;" l |
| | | opts cp_sock.c /^ int opts;$/;" l |
| | | p cp_string.c /^ int p = (s1->len > s2->len) ? s2->len : s1->len;$/;" l |
| | | p test/test_vector.c /^ CP_SOCK *p = NULL;$/;" l |
| | | parity cp_comport.h /^ unsigned char databit, parity, stopbit, flowctrl, is_connted;$/;" m struct:__COM_PORT |
| | | pcPtr cp_string.c /^ char *pcPtr;$/;" l |
| | | pcRecvPtr cp_atcmd.c /^ char *pcRecvPtr = NULL; $/;" l |
| | | pcStart cp_atcmd.c /^ *pcStart = NULL,$/;" l |
| | | pcTab cp_atcmd.c /^ *pcTab = NULL;$/;" l |
| | | pid cp_ppp.c /^ int pid = -1;$/;" l |
| | | pid cp_ppp.c /^ int pid = -1;$/;" l |
| | | pid cp_ppp.c /^ pid_t pid;$/;" l |
| | | pid cp_ppp.h /^ pid_t pid;$/;" m struct:__PPPD_INFO |
| | | pid cp_proc.c /^ char pid[PID_ASCII_SIZE]; $/;" l |
| | | pid cp_proc.c /^ pid_t pid = -1; $/;" l |
| | | pid cp_proc.c /^ pid_t pid; $/;" l |
| | | pid_ascii cp_proc.c /^ char pid_ascii[PID_ASCII_SIZE]; $/;" l |
| | | ping_interval cp_ppp.h /^ long ping_interval;$/;" m struct:__PPP_CTX |
| | | ping_ip cp_ppp.h /^ char ping_ip[INET_ADDRSTRLEN];$/;" m struct:__PPP_CTX |
| | | ping_time cp_ppp.h /^ unsigned long ping_time;$/;" m struct:__PPPD_INFO |
| | | power_off_module cp_gprs.c /^int power_off_module(MODULE_INFO *module)$/;" f |
| | | power_on_module cp_gprs.c /^int power_on_module(MODULE_INFO *module)$/;" f |
| | | ppp_context_init cp_ppp.c /^int ppp_context_init(PPP_CTX *ppp_ctx, MODULE_INFO *module)$/;" f |
| | | ppp_context_term cp_ppp.c /^void ppp_context_term(PPP_CTX *ppp_ctx)$/;" f |
| | | ppp_ctx cp_ppp.c /^ PPP_CTX ppp_ctx; $/;" l |
| | | ppp_stat cp_ppp.c /^ PPP_STAT *ppp_stat = &(ppp_ctx->ppp_stat);$/;" l |
| | | ppp_stat cp_ppp.h /^ PPP_STAT ppp_stat; \/* PPP network statistic *\/$/;" m struct:__PPP_CTX |
| | | ppp_thread_workbody cp_ppp.c /^void *ppp_thread_workbody(void *thread_arg)$/;" f |
| | | pppd_cmd cp_ppp.c /^ char pppd_cmd[PPPD_CMD_LEN];$/;" l |
| | | pppd_info cp_ppp.c /^ PPPD_INFO *pppd_info = &(ppp_ctx->pppd_info);$/;" l |
| | | pppd_info cp_ppp.h /^ PPPD_INFO pppd_info; \/* pppd process information *\/$/;" m struct:__PPP_CTX |
| | | pprev cp_klist.h /^ struct hlist_node **pprev = n->pprev;$/;" l |
| | | pprev cp_klist.h /^ struct hlist_node *next, **pprev;$/;" m struct:hlist_node typeref:struct:hlist_node:: |
| | | prefetch cp_klist.h /^static inline void prefetch(const void *x) {;}$/;" f |
| | | prev cp_klist.h /^ struct list_head *next, *prev;$/;" m struct:list_head typeref:struct:list_head:: |
| | | print_char cp_logger.c /^static char *print_char =$/;" v file: |
| | | print_char cp_string.c /^static char *print_char = $/;" v file: |
| | | print_usage test/swe_tpdud.c /^void print_usage(char *progname)$/;" f |
| | | print_usage test/test_hal.c /^void print_usage(char *progname)$/;" f |
| | | print_version test/comport.c /^void print_version(char *name)$/;" f |
| | | privt cp_sock.h /^ void *privt; \/* socket private data *\/$/;" m struct:_CP_SOCK |
| | | privt_free cp_sock.h /^ PRIVT_FREE privt_free; \/* private data free function if it's malloc *\/$/;" m struct:_CP_SOCK |
| | | prn cp_logger.c /^ char prn[LINELEN];$/;" l |
| | | prn cp_string.c /^ char prn[LINELEN];$/;" l |
| | | proc_uplink_event test/swe_tpdud.c /^int proc_uplink_event(CP_SOCK *ulink)$/;" f |
| | | progname test/comport.c /^ char *progname = NULL;$/;" l |
| | | progname test/test_hal.c /^ char *progname=NULL;$/;" l |
| | | ptpaddr cp_ppp.h /^ char ptpaddr[INET_ADDRSTRLEN];$/;" m struct:__PPPD_INFO |
| | | ptr cp_atcmd.c /^ char *ptr = NULL;$/;" l |
| | | ptr cp_atcmd.c /^ char *ptr = NULL;$/;" l |
| | | ptr cp_common.h /^ void *ptr;$/;" l |
| | | ptr cp_comport.c /^ char *ptr, *end;$/;" l |
| | | ptr cp_iniparser.c /^ char *ptr = NULL; $/;" l |
| | | ptr cp_ppp.c /^ char *ptr;$/;" l |
| | | ptr test/comport.c /^ char *ptr = NULL;$/;" l |
| | | pwd cp_ppp.h /^ char pwd[PWD_LEN];$/;" m struct:__APN_ACCOUNT |
| | | pwr_status cp_gprs.h /^ unsigned char pwr_status; \/* Current module power status *\/$/;" m struct:__MODULE_INFO |
| | | queue test/test_queue.c /^ CP_QUEUE *queue = NULL;$/;" l |
| | | raddr cp_sock.h /^ char raddr[16]; \/* remote IP address *\/$/;" m struct:_CP_SOCK |
| | | raddr test/swe_tpdud.h /^ char raddr[32]; \/* uplink remote listen port *\/$/;" m struct:_SWE_TPDU |
| | | rb_clear cp_ringbuf.c /^void rb_clear (struct ring_buffer *rb) {$/;" f |
| | | rb_data_size cp_ringbuf.c /^int rb_data_size (struct ring_buffer *rb) {$/;" f |
| | | rb_free_size cp_ringbuf.c /^int rb_free_size (struct ring_buffer *rb){$/;" f |
| | | rb_init cp_ringbuf.c /^void rb_init (struct ring_buffer *ring, u_char* buff, int size) {$/;" f |
| | | rb_peek cp_ringbuf.c /^u_char rb_peek(struct ring_buffer* rb, int index) {$/;" f |
| | | rb_read cp_ringbuf.c /^int rb_read (struct ring_buffer *rb, u_char * buf, int max) {$/;" f |
| | | rb_write cp_ringbuf.c /^rb_write (struct ring_buffer *rb, u_char * buf, int len)$/;" f |
| | | rbuf cp_sock.c /^ cp_string *rbuf;$/;" l |
| | | rbuf cp_sock.h /^ cp_string *rbuf; \/* receive buffer *\/$/;" m struct:_CP_SOCK |
| | | rbuf test/test_hh.c /^ unsigned char rbuf[10];$/;" l |
| | | rc cp_logger.c /^ int rc = 0;$/;" l |
| | | rc cp_logger.c /^ int rc;$/;" l |
| | | rc cp_string.c /^ int rc = $/;" l |
| | | rc cp_string.c /^ int rc = memcmp(s1->data, s2->data, p);$/;" l |
| | | rc cp_string.c /^ int rc;$/;" l |
| | | rcv test/test_string.c /^ cp_string *rcv;$/;" l |
| | | rd_pointer cp_ringbuf.h /^ int rd_pointer;$/;" m struct:ring_buffer |
| | | read cp_sock.h /^ CP_SOCK_EVENT_CALLBACK read;$/;" m struct:_CP_SOCK_CALLBACK |
| | | read_len cp_string.c /^ int read_len;$/;" l |
| | | ready cp_gprs.h /^ unsigned char ready; \/* SIM card regist and can work or not *\/$/;" m struct:__MODULE_INFO |
| | | rear cp_queue.h /^ CP_QNODE *rear;$/;" m struct:_CP_QUEUE |
| | | record_daemon_pid cp_proc.c /^int record_daemon_pid(const char *pid_file)$/;" f |
| | | recv_buf cp_atcmd.c /^ char recv_buf[ATCMD_REPLY_LEN];$/;" l |
| | | recv_buf cp_atcmd.c /^ char recv_buf[ATCMD_REPLY_LEN]; $/;" l |
| | | recv_buf cp_atcmd.c /^ char recv_buf[ATCMD_REPLY_LEN];$/;" l |
| | | recv_size test/comport.c /^ int recv_size = 0;$/;" l |
| | | reg cp_gprs.c /^ REGISTER_INFO *reg = &(module->reg); \/* SIM card Register information *\/ $/;" l |
| | | reg cp_gprs.h /^ REGISTER_INFO reg; \/* SIM card register network information *\/$/;" m struct:__MODULE_INFO |
| | | res cp_fds.c /^ struct rlimit res;$/;" l |
| | | res cp_sock.c /^ struct addrinfo *res = NULL;$/;" l |
| | | res cp_string.c /^ cp_string *res = NULL;$/;" l |
| | | res cp_string.c /^ cp_string *res;$/;" l |
| | | result cp_string.c /^ char *result;$/;" l |
| | | ret cp_iniparser.c /^ int ret ;$/;" l |
| | | retVal cp_proc.c /^ int retVal = -1; $/;" l |
| | | retval cp_atcmd.c /^ int retval = -1; $/;" l |
| | | retval cp_atcmd.c /^ int retval;$/;" l |
| | | retval cp_atcmd.c /^ int retval; $/;" l |
| | | retval cp_atcmd.c /^ int retval;$/;" l |
| | | retval cp_atcmd.c /^ int retval = 0; $/;" l |
| | | retval cp_atcmd.c /^ int retval, stat = -1;$/;" l |
| | | retval cp_atcmd.c /^ int retval;$/;" l |
| | | retval cp_atcmd.c /^ int retval=0; $/;" l |
| | | retval cp_atcmd.c /^ int retval;$/;" l |
| | | retval cp_atcmd.c /^ int retval;$/;" l |
| | | retval cp_comport.c /^ int retval = -1;$/;" l |
| | | retval cp_comport.c /^ int retval = 0; \/\/ Function return value$/;" l |
| | | retval cp_comport.c /^ int retval = 0;$/;" l |
| | | retval cp_gprs.c /^ int retval = 0;$/;" l |
| | | retval cp_gprs.c /^ int i, retval = -1;$/;" l |
| | | retval cp_ppp.c /^ int retval;$/;" l |
| | | retval cp_ppp.c /^ int retval = -1;$/;" l |
| | | retval cp_proc.c /^ int retval = 0;$/;" l |
| | | retval cp_proc.c /^ int retval, fd; $/;" l |
| | | retval test/comport.c /^ int retval = -1;$/;" l |
| | | retval test/comport.c /^ int retval = 0;$/;" l |
| | | ring_buffer cp_ringbuf.h /^struct ring_buffer {$/;" s |
| | | rlist cp_sock.h /^ struct list_head rlist; \/* The list_head member position just for the registry list *\/$/;" m struct:_CP_SOCK typeref:struct:_CP_SOCK::list_head |
| | | rp cp_sock.c /^ struct addrinfo hints, *rp;$/;" l |
| | | rport cp_sock.h /^ int rport; \/* remote port *\/$/;" m struct:_CP_SOCK |
| | | rport test/swe_tpdud.h /^ int rport; \/* uplink remote IP address *\/$/;" m struct:_SWE_TPDU |
| | | rsize cp_sock.h /^ int rsize; \/* ioctl() set socket recv buffer size *\/$/;" m struct:_CP_SOCK |
| | | rtc_tm cp_time.h /^ struct rtc_time rtc_tm; $/;" l |
| | | rv cp_array.c /^ int i, rv = -3;$/;" l |
| | | rv cp_fds.c /^ int rv = 0;$/;" l |
| | | rv cp_fds.c /^ int rv;$/;" l |
| | | rv cp_fds.c /^ int rv;$/;" l |
| | | rv cp_fds.c /^ int rv = 0;$/;" l |
| | | rv cp_gprs.c /^ int rv;$/;" l |
| | | rv cp_gprs.c /^ int i, rv = 0;$/;" l |
| | | rv cp_gprs.c /^ int rv = 0;$/;" l |
| | | rv cp_gprs.c /^ int rv;$/;" l |
| | | rv cp_gprs.c /^ int rv = 0;$/;" l |
| | | rv cp_hal.c /^ int rv = 0;$/;" l |
| | | rv cp_network.c /^ int rv = 0;$/;" l |
| | | rv cp_network.c /^ int rv = 0;$/;" l |
| | | rv cp_sock.c /^ int rv = 0;$/;" l |
| | | rv cp_sock.c /^ int rv;$/;" l |
| | | rv cp_sock.c /^ int rv = 0;$/;" l |
| | | rv cp_sock.c /^ int rv, left;$/;" l |
| | | rv cp_sock.c /^ int rv = 0;$/;" l |
| | | rv cp_time.h /^ int rv, fd = -1;$/;" l |
| | | rv test/swe_tpdud.c /^ int rv = 0;$/;" l |
| | | rv test/swe_tpdud.c /^ int rv;$/;" l |
| | | rv test/test_hal.c /^ int rv = 0;$/;" l |
| | | rv test/test_sock_client.c /^ int rv;$/;" l |
| | | rv test/test_sock_server.c /^ int rv = 0;$/;" l |
| | | rx_packets cp_network.c /^ unsigned long rx_packets = 0;$/;" l |
| | | saddr cp_sock.c /^ struct sockaddr_in *saddr = (struct sockaddr_in *)rp->ai_addr;$/;" l |
| | | saddr cp_sock.c /^ struct sockaddr_in saddr;$/;" l |
| | | saddr cp_sock.c /^ struct sockaddr_in saddr;$/;" l |
| | | saddr cp_sock.h /^ struct sockaddr saddr; \/* sockaddr for connect *\/$/;" m struct:_CP_SOCK typeref:struct:_CP_SOCK::sockaddr |
| | | save cp_vector.c /^ void *save;$/;" l |
| | | sbuf cp_sock.h /^ cp_string *sbuf; \/* send buffer *\/$/;" m struct:_CP_SOCK |
| | | sbuf test/test_hh.c /^ unsigned char sbuf[10]={0x02, 0x48, 0x32, 0x03, 0x20, 0x00, 0x00, 0xF6, 0xBE, 0x03};$/;" l |
| | | seclen cp_iniparser.c /^ int seclen ;$/;" l |
| | | seclen cp_iniparser.c /^ int seclen, nkeys ;$/;" l |
| | | secname cp_iniparser.c /^ char * secname ;$/;" l |
| | | section cp_iniparser.c /^ char section [ASCIILINESZ+1] ;$/;" l |
| | | select_apn cp_ppp.c /^int select_apn(PPP_CTX *ppp_ctx, char *key)$/;" f |
| | | send cp_comport.c /^ int send = 0;$/;" l |
| | | send_atcmd cp_atcmd.c /^int send_atcmd(COM_PORT *comport, char *atCmd, char *expect, char *error,$/;" f |
| | | send_atcmd_check_ok cp_atcmd.c /^int send_atcmd_check_ok(COM_PORT *comport, char *atcmd, unsigned long timeout)$/;" f |
| | | send_atcmd_check_request cp_atcmd.c /^int send_atcmd_check_request(COM_PORT *comport, char *atcmd, unsigned long timeout, char *buf, int buf_len)$/;" f |
| | | send_atcmd_check_value cp_atcmd.c /^int send_atcmd_check_value(COM_PORT *comport, char *atcmd, unsigned long timeout, char *buf, int buf_len)$/;" f |
| | | serv_sock cp_fds.c /^ CP_SOCK *sock, *tsock, *serv_sock;$/;" l |
| | | serv_sock cp_sock.h /^ struct _CP_SOCK *serv_sock; \/* Accept socket used to point to the server socket *\/$/;" m struct:_CP_SOCK typeref:struct:_CP_SOCK::_CP_SOCK |
| | | serv_tpdu test/swe_tpdud.c /^ SWE_TPDU *serv_tpdu;$/;" l |
| | | server_list cp_fds.h /^ struct list_head server_list; \/* a list keep all the listen sockets *\/ $/;" m struct:_CP_FDS typeref:struct:_CP_FDS::list_head |
| | | service cp_sock.c /^ char service[20];$/;" l |
| | | service_route test/test_sock_client.c /^int service_route(CP_SOCK *sock)$/;" f |
| | | service_route test/test_sock_server.c /^int service_route(CP_SOCK *sock)$/;" f |
| | | set_daemon_running cp_proc.c /^int set_daemon_running(const char *pid_file)$/;" f |
| | | set_module_event cp_gprs.c /^void set_module_event(MODULE_INFO *module, int request)$/;" f |
| | | set_module_event_power cp_gprs.c /^int set_module_event_power(MODULE_INFO *module)$/;" f |
| | | set_ppp_disconnect cp_ppp.c /^void set_ppp_disconnect(PPP_CTX *ppp_ctx)$/;" f |
| | | set_settings cp_comport.c /^void set_settings(COM_PORT * comport, const char *settings)$/;" f |
| | | settings test/comport.c /^ char *settings = "8N1N";$/;" l |
| | | sigact cp_proc.c /^ struct sigaction sigact, sigign;$/;" l |
| | | sigact test/comport.c /^ struct sigaction sigact;$/;" l |
| | | sigign cp_proc.c /^ struct sigaction sigact, sigign;$/;" l |
| | | signal cp_atcmd.c /^ int signal = -1;$/;" l |
| | | signal cp_atcmd.h /^ int signal; \/* GPRS signal *\/ $/;" m struct:_REGISTER_INFO |
| | | signal cp_proc.h /^ int signal;$/;" m struct:__CP_PROC_SIG |
| | | signal_handler test/comport.c /^void signal_handler(int i_sig)$/;" f |
| | | sin cp_network.c /^ struct sockaddr_in *sin; $/;" l |
| | | sin cp_ppp.c /^ struct sockaddr_in *sin; $/;" l |
| | | size cp_array.h /^ int size;$/;" m struct:_CP_ARRAY |
| | | size cp_dictionary.h /^ int size ; \/** Storage size *\/$/;" m struct:_dictionary_ |
| | | size cp_logger.h /^ int size;$/;" m struct:_cp_logger |
| | | size cp_queue.h /^ int size;$/;" m struct:_CP_QUEUE |
| | | size cp_ringbuf.h /^ int size;$/;" m struct:ring_buffer |
| | | size cp_string.c /^ int size;$/;" l |
| | | size cp_string.h /^ int size; \/**< size allocated *\/$/;" m struct:_cp_string |
| | | size cp_vector.h /^ int size;$/;" m struct:_CP_VECTOR |
| | | snd test/test_string.c /^ cp_string *snd;$/;" l |
| | | so_linger cp_sock.c /^ struct linger so_linger;$/;" l |
| | | sock cp_fds.c /^ CP_SOCK *sock;$/;" l |
| | | sock cp_fds.c /^ CP_SOCK *sock;$/;" l |
| | | sock cp_fds.c /^ CP_SOCK *sock = NULL, *tsock;$/;" l |
| | | sock cp_fds.c /^ CP_SOCK *sock, *tsock, *serv_sock;$/;" l |
| | | sock cp_fds.c /^ CP_SOCK *sock, *tsock;$/;" l |
| | | sock cp_fds.c /^ CP_SOCK *sock;$/;" l |
| | | sock cp_fds.c /^ CP_SOCK *sock = NULL;$/;" l |
| | | sock cp_network.c /^ CP_SOCK *sock = NULL;$/;" l |
| | | sock test/swe_tpdud.c /^ CP_SOCK *sock;$/;" l |
| | | sock test/test_array.c /^ CP_SOCK *sock = NULL;$/;" l |
| | | sock test/test_klist.c /^ CP_SOCK *sock, *tsock;$/;" l |
| | | sock test/test_queue.c /^ CP_SOCK *sock = NULL;$/;" l |
| | | sock test/test_sock_client.c /^ CP_SOCK *sock = NULL;$/;" l |
| | | sock test/test_sock_server.c /^ CP_SOCK *sock;$/;" l |
| | | sock_list test/test_klist.c /^ struct list_head sock_list;$/;" l |
| | | sock_poll cp_sock.c /^ struct pollfd sock_poll;$/;" l |
| | | split_string_to_value cp_string.c /^int split_string_to_value(char *str, char *fmt, ...)$/;" f |
| | | ssize cp_sock.h /^ int ssize; \/* ioctl() set socket send buffer size *\/$/;" m struct:_CP_SOCK |
| | | stExcpFds cp_comport.c /^ fd_set stReadFds, stExcpFds;$/;" l |
| | | stReadFds cp_comport.c /^ fd_set stReadFds, stExcpFds;$/;" l |
| | | stTime cp_comport.c /^ struct timeval stTime;$/;" l |
| | | sta cp_iniparser.c /^ line_status sta ;$/;" l |
| | | start cp_atcmd.c /^ char *start;$/;" l |
| | | start_ppp_connect cp_ppp.c /^int start_ppp_connect(PPP_CTX *ppp_ctx)$/;" f |
| | | start_ppp_dial_cmd cp_ppp.c /^int start_ppp_dial_cmd(COM_PORT *comport, APN_ACCOUNT *apn, char *ppp_dev)$/;" f |
| | | start_thread_ppp cp_ppp.c /^int start_thread_ppp(MODULE_INFO *module)$/;" f |
| | | start_time cp_gprs.c /^ static unsigned long start_time ;$/;" l file: |
| | | start_time cp_ppp.h /^ unsigned long start_time;$/;" m struct:__PPPD_INFO |
| | | stat cp_atcmd.c /^ int retval, stat = -1;$/;" l |
| | | status cp_atcmd.c /^ int status;$/;" l |
| | | status cp_hal.c /^ int status;$/;" l |
| | | status cp_ppp.h /^ unsigned char status; \/* Current PPP connection status *\/$/;" m struct:__PPP_CTX |
| | | status cp_sock.h /^ unsigned char status; \/* current socket status *\/$/;" m struct:_CP_SOCK |
| | | stop cp_proc.h /^ unsigned stop; \/* 0: Not term 1: Stop *\/$/;" m struct:__CP_PROC_SIG |
| | | stop_ppp_connect cp_ppp.c /^int stop_ppp_connect(PPP_CTX *ppp_ctx)$/;" f |
| | | stop_tpdu_service test/swe_tpdud.c /^static void stop_tpdu_service(SWE_TPDU *tpdu)$/;" f file: |
| | | stopbit cp_comport.h /^ unsigned char databit, parity, stopbit, flowctrl, is_connted;$/;" m struct:__COM_PORT |
| | | str cp_iniparser.c /^ char * str ;$/;" l |
| | | str cp_ppp.c /^ char *str;$/;" l |
| | | str cp_string.c /^ cp_string *str = t_malloc(sizeof(cp_string));$/;" l |
| | | str cp_string.c /^ cp_string *str;$/;" l |
| | | string cp_string.c /^ static char string[1024]; $/;" l file: |
| | | strlwc cp_iniparser.c /^static char * strlwc(const char * s)$/;" f file: |
| | | strstrip cp_iniparser.c /^static char * strstrip(const char * s)$/;" f file: |
| | | sval cp_iniparser.c /^ char * sval ;$/;" l |
| | | t cp_dictionary.c /^ char * t ;$/;" l |
| | | t1 cp_gsmmux.h /^ unsigned int t1;$/;" m struct:gsm_config |
| | | t2 cp_gsmmux.h /^ unsigned int t2;$/;" m struct:gsm_config |
| | | t3 cp_gsmmux.h /^ unsigned int t3;$/;" m struct:gsm_config |
| | | t_free cp_common.h 60;" d |
| | | t_free cp_common.h 63;" d |
| | | t_malloc cp_common.h 61;" d |
| | | t_malloc cp_common.h 64;" d |
| | | task_array cp_fds.h /^ CP_ARRAY *task_array; \/* an array keep all these pending\/or other special task socket *\/ $/;" m struct:_CP_FDS |
| | | test_buzzer test/test_hal.c /^ int test_buzzer = 0;$/;" l |
| | | test_buzzer_hal_api test/test_hal.c /^void test_buzzer_hal_api(void)$/;" f |
| | | test_gprs test/test_hal.c /^ int test_gprs = 0;$/;" l |
| | | test_gprs_hal_api test/test_hal.c /^void test_gprs_hal_api(void)$/;" f |
| | | test_led test/test_hal.c /^ int test_led = 0;$/;" l |
| | | test_led_hal_api test/test_hal.c /^void test_led_hal_api(void)$/;" f |
| | | thread_attr cp_proc.c /^ pthread_attr_t thread_attr; $/;" l |
| | | thread_id cp_ppp.h /^ pthread_t thread_id; \/* PPP Thread ID, RFU *\/$/;" m struct:__PPP_CTX |
| | | thread_start cp_proc.c /^int thread_start(pthread_t * thread_id, THREAD_BODY * thread_workbody, void *thread_arg)$/;" f |
| | | tid cp_ppp.c /^ pthread_t tid;$/;" l |
| | | time cp_atcmd.h /^ char time[15];$/;" m struct:_GPRS_LOCATION |
| | | time_elapsed cp_time.h /^static inline unsigned long time_elapsed(unsigned long start)$/;" f |
| | | time_now cp_time.h /^static inline unsigned long time_now()$/;" f |
| | | timeout cp_fds.h /^ int timeout; \/* epoll_wait timeout value *\/$/;" m struct:_CP_FDS |
| | | timestr cp_logger.c /^ char timestr[256];$/;" l |
| | | tmp cp_atcmd.c /^ char tmp[ATCMD_REPLY_LEN];$/;" l |
| | | tmp cp_comport.c /^ long tmp;$/;" l |
| | | tmp cp_iniparser.c /^ char tmp [ASCIILINESZ+1] ;$/;" l |
| | | tmp cp_ppp.c /^ char tmp[64];$/;" l |
| | | tmp cp_ppp.c /^ char tmp[64];$/;" l |
| | | tmp cp_queue.c /^ CP_QNODE *node, *tmp;$/;" l |
| | | tmp test/test_array.c /^ CP_SOCK *tmp = NULL;$/;" l |
| | | tmp test/test_queue.c /^ CP_SOCK *tmp = NULL;$/;" l |
| | | tnow cp_time.h /^ struct tm *tnow = localtime(&now); $/;" l |
| | | total cp_ringbuf.c /^ int total;$/;" l |
| | | total cp_string.c /^ int total = 0;$/;" l |
| | | tpdu test/swe_tpdud.c /^ SWE_TPDU *tpdu;$/;" l |
| | | tpdu test/swe_tpdud.c /^ SWE_TPDU tpdu = {.lport=TPDUD_PORT, .raddr=HOSTSIM_IP, .rport=HOSTSIM_PORT};$/;" l |
| | | tpdu test/swe_tpdud.c /^ SWE_TPDU *tpdu = NULL; $/;" l |
| | | tpdu_connect_uplink test/swe_tpdud.c /^int tpdu_connect_uplink(SWE_TPDU *tpdu)$/;" f |
| | | tpdu_service_route test/swe_tpdud.c /^int tpdu_service_route(CP_SOCK *dlink)$/;" f |
| | | travel_list test/test_klist.c /^void travel_list(struct list_head *head)$/;" f |
| | | tsock cp_fds.c /^ CP_SOCK *sock = NULL, *tsock;$/;" l |
| | | tsock cp_fds.c /^ CP_SOCK *sock, *tsock, *serv_sock;$/;" l |
| | | tsock cp_fds.c /^ CP_SOCK *sock, *tsock;$/;" l |
| | | tsock test/test_klist.c /^ CP_SOCK *sock, *tsock;$/;" l |
| | | ttystate cp_comport.c /^ struct termios ttystate;$/;" l |
| | | tv cp_comport.c /^ struct timeval tv;$/;" l |
| | | tx_packets cp_network.c /^ unsigned long tx_packets = 0;$/;" l |
| | | type cp_atcmd.h /^ int type; \/* SIM card register type: REG_HOMEWORK,REG_SEARCHING... *\/$/;" m struct:_REGISTER_INFO |
| | | type cp_ppp.c /^ unsigned char type = APN_2G;$/;" l |
| | | uid cp_ppp.h /^ char uid[UID_LEN]; $/;" m struct:__APN_ACCOUNT |
| | | ulCollisions cp_ppp.h /^ unsigned long ulCollisions;$/;" m struct:__PPP_STAT |
| | | ulRx_CRC_Errors cp_ppp.h /^ unsigned long ulRx_CRC_Errors; \/\/ recved pkt with crc error$/;" m struct:__PPP_STAT |
| | | ulRx_Compressed cp_ppp.h /^ unsigned long ulRx_Compressed;$/;" m struct:__PPP_STAT |
| | | ulRx_Dropped cp_ppp.h /^ unsigned long ulRx_Dropped; \/\/ no space in linux buffers$/;" m struct:__PPP_STAT |
| | | ulRx_Errors cp_ppp.h /^ unsigned long ulRx_Errors; \/\/ bad packets received $/;" m struct:__PPP_STAT |
| | | ulRx_FIFO_Errors cp_ppp.h /^ unsigned long ulRx_FIFO_Errors; \/\/ recv'r fifo overrun $/;" m struct:__PPP_STAT |
| | | ulRx_Frame_Errors cp_ppp.h /^ unsigned long ulRx_Frame_Errors; \/\/ recv'd frame alignment error$/;" m struct:__PPP_STAT |
| | | ulRx_Length_Errors cp_ppp.h /^ unsigned long ulRx_Length_Errors;$/;" m struct:__PPP_STAT |
| | | ulRx_Missed_Errors cp_ppp.h /^ unsigned long ulRx_Missed_Errors; \/\/ receiver missed packet $/;" m struct:__PPP_STAT |
| | | ulRx_Multicast cp_ppp.h /^ unsigned long ulRx_Multicast; \/\/ multicast packets received $/;" m struct:__PPP_STAT |
| | | ulRx_Over_Errors cp_ppp.h /^ unsigned long ulRx_Over_Errors; \/\/ receiver ring buff overflow$/;" m struct:__PPP_STAT |
| | | ulStartTime cp_atcmd.c /^ unsigned long ulStartTime; $/;" l |
| | | ulTmp cp_time.h /^ unsigned long ulTmp;$/;" l |
| | | ulTx_Aborted_Errors cp_ppp.h /^ unsigned long ulTx_Aborted_Errors;$/;" m struct:__PPP_STAT |
| | | ulTx_Carrier_Errors cp_ppp.h /^ unsigned long ulTx_Carrier_Errors;$/;" m struct:__PPP_STAT |
| | | ulTx_Compressed cp_ppp.h /^ unsigned long ulTx_Compressed;$/;" m struct:__PPP_STAT |
| | | ulTx_Dropped cp_ppp.h /^ unsigned long ulTx_Dropped; \/\/ no space available in linux$/;" m struct:__PPP_STAT |
| | | ulTx_Errors cp_ppp.h /^ unsigned long ulTx_Errors; \/\/ packet transmit problems$/;" m struct:__PPP_STAT |
| | | ulTx_FIFO_Errors cp_ppp.h /^ unsigned long ulTx_FIFO_Errors;$/;" m struct:__PPP_STAT |
| | | ulTx_Heartbeat_Errors cp_ppp.h /^ unsigned long ulTx_Heartbeat_Errors;$/;" m struct:__PPP_STAT |
| | | ulTx_Window_Errors cp_ppp.h /^ unsigned long ulTx_Window_Errors;$/;" m struct:__PPP_STAT |
| | | ulink test/swe_tpdud.c /^ CP_SOCK *ulink;$/;" l |
| | | ulink test/swe_tpdud.h /^ CP_SOCK *ulink; \/* connect to hostsim socket *\/$/;" m struct:_SWE_TPDU |
| | | ullRx_Bytes cp_ppp.h /^ unsigned long long ullRx_Bytes; \/\/ total bytes received $/;" m struct:__PPP_STAT |
| | | ullRx_Packets cp_ppp.h /^ unsigned long long ullRx_Packets; \/\/ total packets received $/;" m struct:__PPP_STAT |
| | | ullTx_Bytes cp_ppp.h /^ unsigned long long ullTx_Bytes; \/\/ total bytes transmitted $/;" m struct:__PPP_STAT |
| | | ullTx_Packets cp_ppp.h /^ unsigned long long ullTx_Packets; \/\/ total packets transmitted$/;" m struct:__PPP_STAT |
| | | unused cp_gsmmux.h /^ unsigned int unused[8]; \/* Padding for expansion without breaking stuff *\/$/;" m struct:gsm_config |
| | | usage test/comport.c /^void usage(char *name)$/;" f |
| | | used cp_comport.h /^ unsigned char used; \/* This comport used or not now *\/$/;" m struct:__COM_PORT |
| | | used cp_vector.h /^ int used;$/;" m struct:_CP_VECTOR |
| | | users cp_gprs.h /^ int users; \/* How many users use the module now *\/$/;" m struct:__MODULE_INFO |
| | | v test/test_vector.c /^ CP_VECTOR *v = cp_vector_init(1024);$/;" l |
| | | val cp_dictionary.c /^ char * val ;$/;" l |
| | | val cp_dictionary.h /^ char ** val ; \/** List of string values *\/$/;" m struct:_dictionary_ |
| | | val cp_iniparser.c /^ char val [ASCIILINESZ+1] ;$/;" l |
| | | vector cp_vector.c /^ CP_VECTOR *vector = NULL;$/;" l |
| | | who cp_gprs.c /^ char *who = "atcmd_check_ready()";$/;" l |
| | | who cp_gprs.c /^ char *who = "atcmd_inspect_status()";$/;" l |
| | | wr_pointer cp_ringbuf.h /^ int wr_pointer;$/;" m struct:ring_buffer |
| | | write cp_sock.h /^ CP_SOCK_EVENT_CALLBACK write;$/;" m struct:_CP_SOCK_CALLBACK |
| | | xstrdup cp_dictionary.c /^static char * xstrdup(const char * s)$/;" f file: |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue <guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: comport.c |
| | | * Description: This file used to do ioctl() on common device or communicate |
| | | * with serial port/TTY device. |
| | | * |
| | | * Version: 1.0.0(10/18/2011~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "10/18/2011 10:08:05 AM" |
| | | * |
| | | ********************************************************************************/ |
| | | #include <getopt.h> |
| | | #include <libgen.h> |
| | | #include <sys/ioctl.h> |
| | | |
| | | #include "cp_comport.h" |
| | | #include "cp_common.h" |
| | | #include "version.h" |
| | | |
| | | unsigned char g_ucProcToken = 0x01; |
| | | unsigned char g_ucCtrlZ; |
| | | |
| | | void print_version(char *name); |
| | | void usage(char *name); |
| | | int do_ioctl(char *dev_name, int cmd, int arg); |
| | | void signal_handler(int i_sig); |
| | | |
| | | int main(int argc, char **argv) |
| | | { |
| | | int opt = 0; |
| | | int retval = 0; |
| | | int recv_size = 0; |
| | | int i; |
| | | char *dev_name = NULL; |
| | | int baudrate = 115200; |
| | | char *settings = "8N1N"; |
| | | char buf[512]; |
| | | unsigned char disp_mode = 0x00; |
| | | |
| | | struct sigaction sigact; |
| | | |
| | | struct option long_options[] = { |
| | | {"device", required_argument, NULL, 'd'}, |
| | | {"baudrate", required_argument, NULL, 'b'}, |
| | | {"settings", required_argument, NULL, 's'}, |
| | | {"ioctl", required_argument, NULL, 'i'}, |
| | | {"hex", no_argument, NULL, 'x'}, |
| | | {"version", no_argument, NULL, 'v'}, |
| | | {"help", no_argument, NULL, 'h'}, |
| | | {NULL, 0, NULL, 0} |
| | | }; |
| | | |
| | | while ((opt = getopt_long(argc, argv, "d:b:s:ivh", long_options, NULL)) != -1) |
| | | { |
| | | switch (opt) |
| | | { |
| | | case 'd': |
| | | dev_name = optarg; |
| | | break; |
| | | case 'b': |
| | | baudrate = atoi(optarg); |
| | | break; |
| | | case 's': /* Default settings as 8N1N */ |
| | | settings = optarg; |
| | | break; |
| | | case 'i': |
| | | if (5 != argc) |
| | | { |
| | | usage(argv[0]); |
| | | } |
| | | else |
| | | { |
| | | do_ioctl(argv[2], atoi(argv[3]), atoi(argv[4])); |
| | | } |
| | | return 0; |
| | | case 'x': /* Display receive data as Hex mode */ |
| | | disp_mode = 0x01; |
| | | break; |
| | | case 'v': /* version */ |
| | | print_version(argv[0]); |
| | | return 0; |
| | | case 'h': /* help */ |
| | | usage(argv[0]); |
| | | return 0; |
| | | default: |
| | | break; |
| | | } /* end of "switch(opt)" */ |
| | | } |
| | | |
| | | if (argc < 2) |
| | | { |
| | | usage(argv[0]); |
| | | return 0; |
| | | } |
| | | |
| | | COM_PORT *comport = NULL; |
| | | if (NULL == (comport = comport_init(dev_name, baudrate, settings))) |
| | | { |
| | | printf("Comport initialize failure.\n"); |
| | | return -1; |
| | | } |
| | | |
| | | if ( (retval=comport_open(comport)) < 0) |
| | | { |
| | | printf("Failed to open %s with baudrate %d, %s. RetCode [%d]\n", dev_name, baudrate, |
| | | settings, retval); |
| | | return -1; |
| | | } |
| | | |
| | | nonblock(); |
| | | |
| | | /* Process level signal handler */ |
| | | sigemptyset(&sigact.sa_mask); |
| | | sigact.sa_flags = 0; |
| | | sigact.sa_handler = signal_handler; |
| | | |
| | | sigaction(SIGTERM, &sigact, NULL); /* catch terminate signal */ |
| | | sigaction(SIGINT, &sigact, NULL); /* catch interrupt signal */ |
| | | sigaction(SIGSEGV, &sigact, NULL); /* catch segmentation faults */ |
| | | sigaction(SIGTSTP, &sigact, NULL); /* catch ctrl+Z */ |
| | | sigaction(SIGSTOP, &sigact, NULL); /* catch ctrl+Z */ |
| | | |
| | | while (0x01 == g_ucProcToken) |
| | | { |
| | | recv_size = comport_recv(comport, buf, sizeof(buf) - 1, 10); |
| | | if (recv_size > 0) |
| | | { |
| | | for (i = 0; i < recv_size; i++) |
| | | { |
| | | if (0 == disp_mode) |
| | | printf("%c", buf[i]); |
| | | else |
| | | printf("%02X ", buf[i]); |
| | | } |
| | | fflush(stdout); |
| | | } |
| | | if (0 != kbhit()) |
| | | { |
| | | retval = fgetc(stdin); |
| | | |
| | | if (0x0A == retval) |
| | | { |
| | | buf[0] = 0x0D; /* 13 == 0x0D */ |
| | | } |
| | | else |
| | | { |
| | | buf[0] = retval; |
| | | } |
| | | |
| | | comport_send(comport, buf, 1); |
| | | } |
| | | else if (0x00 != g_ucCtrlZ) |
| | | { |
| | | g_ucCtrlZ = 0x00; |
| | | buf[0] = 0x1A; |
| | | comport_send(comport, buf, 1); |
| | | } |
| | | } |
| | | |
| | | comport_term(comport); |
| | | return 0; |
| | | } /* ----- End of main() ----- */ |
| | | |
| | | void print_version(char *name) |
| | | { |
| | | char *progname = NULL; |
| | | char *ptr = NULL; |
| | | |
| | | ptr = strdup(name); |
| | | progname = basename(ptr); |
| | | |
| | | printf("%s version: %d.%d.%d Build %04d on %s\n", progname, MAJOR, MINOR, REVER, SVNVER, DATE); |
| | | printf("Copyright (C) 2010 guowenxue <guowenxue@gmail.com>\n"); |
| | | |
| | | t_free(ptr); |
| | | return; |
| | | } |
| | | |
| | | void usage(char *name) |
| | | { |
| | | char *progname = NULL; |
| | | char *ptr = NULL; |
| | | |
| | | ptr = strdup(name); |
| | | progname = basename(ptr); |
| | | printf("Usage1: comport -d <device> [-b <baudrate>][-s <settings>] [-x]\n"); |
| | | printf("Usage2: comport [-i <driver port> <cmd> <arg>][--help][--version]\n"); |
| | | printf(" -d[device ] device name\n"); |
| | | printf(" -b[baudrate] device baudrate (115200, 57600, 19200, 9600), default is 115200\n"); |
| | | printf(" -s[settings] device settings as like 8N1N(default setting)\n"); |
| | | printf(" - data bits: 8, 7\n"); |
| | | printf(" - parity: N=None, O=Odd, E=Even, S=Space\n"); |
| | | printf(" - stop bits: 1, 0\n"); |
| | | printf(" - flow control: N=None, H=Hardware, S=Software, B=Both\n"); |
| | | printf(" -x[hex ] display received data in hex format\n"); |
| | | printf(" -i[ioctl ] ioctl system call (cmd & arg only support int)\n"); |
| | | printf(" -v[version ] Display the program version\n"); |
| | | printf(" -h[help ] Display this help information\n"); |
| | | |
| | | print_version(progname); |
| | | |
| | | t_free(ptr); |
| | | |
| | | return; |
| | | } |
| | | |
| | | int do_ioctl(char *dev_name, int cmd, int arg) |
| | | { |
| | | int fd = -1; |
| | | int retval = -1; |
| | | if (((fd = open(dev_name, O_RDWR)) < 0)) |
| | | { |
| | | printf("Open device \"%s\" failure: %s\n", dev_name, strerror(errno)); |
| | | return -1; |
| | | } |
| | | |
| | | retval = ioctl(fd, cmd, arg); |
| | | printf("ioctl (%s, %d, %d) returned %d\n", dev_name, cmd, arg, retval); |
| | | |
| | | close(fd); |
| | | return retval; |
| | | } |
| | | |
| | | void signal_handler(int i_sig) |
| | | { |
| | | if (SIGTERM == i_sig || SIGINT == i_sig) |
| | | { |
| | | g_ucProcToken = 0x00; |
| | | } |
| | | else if (20 == i_sig) |
| | | { |
| | | g_ucCtrlZ = 0x01; |
| | | } |
| | | } |
| | | |
| | | |
New file |
| | |
| | | #********************************************************************************* |
| | | # Copyright: (C) 2012 Guo Wenxue <guowenxue@gmail.com> |
| | | # All rights reserved. |
| | | # |
| | | # Filename: Makefile |
| | | # Description: This Makefile used to compile all the C source code file in current |
| | | # folder to respective excutable binary files. |
| | | # |
| | | # Version: 1.0.0(10/08/2011~) |
| | | # Author: Guo Wenxue <guowenxue@gmail.com> |
| | | # ChangeLog: 1, Release initial version on "11/11/2011 01:29:33 PM" |
| | | # |
| | | #********************************************************************************/ |
| | | |
| | | PWD=$(shell pwd) |
| | | LIB_PATH=$(shell dirname ${PWD}) |
| | | LIB_NAME=$(shell basename ${LIB_PATH}) |
| | | INSTPATH=/tftp |
| | | |
| | | #ARCH ?= i386 |
| | | #ARCH?=arm926t |
| | | ARCH?=arm920t |
| | | |
| | | #LINK_MODE=STATIC |
| | | MODE=PRODUCTION |
| | | DEBUG=1 |
| | | |
| | | CFLAGS+=-Wall -Werror |
| | | #CFLAGS+=-Wno-unused |
| | | |
| | | ifeq ("${MODE}", "PRODUCTION") |
| | | CFLAGS+=-DPRODUCTION_MODE |
| | | endif |
| | | ifdef DEBUG |
| | | CFLAGS+=-g -DDEBUG |
| | | endif |
| | | |
| | | COMPILE_DATE=$(shell date -u +"%Y-%m-%d %H:%M") |
| | | VPATH= . |
| | | SRCS = $(wildcard ${VPATH}/*.c) |
| | | OBJS = $(patsubst %.c,%.o,$(SRCS)) |
| | | |
| | | TMP=$(shell echo $(ARCH) | tr "[A-Z]" "[a-z]") |
| | | ifneq (,$(filter i386,$(TMP))) |
| | | CROSS_COMPILE= |
| | | else |
| | | CROSS_COMPILE=/opt/buildroot-2012.08/$(ARCH)/usr/bin/arm-linux- |
| | | endif |
| | | |
| | | CFLAGS+=-I${LIB_PATH} |
| | | LDFLAGS+=-L${LIB_PATH} -l${LIB_NAME} |
| | | |
| | | export CC=${CROSS_COMPILE}gcc |
| | | export CXX=${CROSS_COMPILE}g++ |
| | | export AR=${CROSS_COMPILE}ar |
| | | export AS=${CROSS_COMPILE}as |
| | | export RANLIB=${CROSS_COMPILE}ranlib |
| | | export STRIP=${CROSS_COMPILE}strip |
| | | export CFLAGS |
| | | export LDFLAGS |
| | | export ARCH |
| | | export LINK_MODE |
| | | |
| | | LDFLAGS+=-lpthread |
| | | ifeq ("${LINK_MODE}", "STATIC") |
| | | CFLAGS+=--static |
| | | LDFLAGS+=-static |
| | | else |
| | | LDFLAGS+=-ldl |
| | | endif |
| | | |
| | | SRCFILES = $(wildcard *.c) |
| | | BINARIES=$(SRCFILES:%.c=%) |
| | | |
| | | all: entry version binaries install |
| | | entry: |
| | | @echo " "; |
| | | @echo " ========================================================="; |
| | | @echo " ** Compile \"${BINARIES}\" for ${ARCH} "; |
| | | @echo " ========================================================="; |
| | | |
| | | version: |
| | | @echo "/* Generated by makefile, don't Edit it by hand */" > version.h |
| | | @echo "#define DATE \"$(COMPILE_DATE)\"" >> version.h |
| | | @echo "#define MAJOR 1" >>version.h |
| | | @echo "#define MINOR 0" >>version.h |
| | | @echo "#define REVER 0" >>version.h |
| | | @if [ -f .svn/entries ] ; then \ |
| | | echo "#define SVNVER `sed -n -e 11p .svn/entries`" >>version.h; \ |
| | | else \ |
| | | echo "#define SVNVER 0" >>version.h; \ |
| | | fi; |
| | | @echo "" >> version.h |
| | | @echo '#define version(progname) printf("%s Version %d.%d.%d Build @%05d (%s)\n", progname, MAJOR, MINOR, REVER,SVNVER, DATE)' >> version.h |
| | | @echo '#define copyright() printf("Copyright: (C) 2012 Guo Wenxue<Email:guowenxue@gmail.com\n")' >>version.h |
| | | @echo '#define banner(progname) {version(progname); copyright(); printf("\n");}' >>version.h |
| | | @echo "" >> version.h |
| | | |
| | | binaries: ${BINARIES} |
| | | @echo " Compile over" |
| | | |
| | | %: %.c |
| | | $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) |
| | | |
| | | tag: |
| | | @ctags --c-kinds=+defglmnstuvx --langmap=c:.c.h.ho.hem.het.hec.hev.him.hit.hic.hiv -R . |
| | | @cscope -Rbq |
| | | |
| | | install: |
| | | @cp $(BINARIES) ${INSTPATH} |
| | | |
| | | clean: |
| | | @rm -f version.h |
| | | @rm -f *.o *.lo $(BINARIES) |
| | | @rm -rf *.gdb *.a *.so *.elf* |
| | | @rm -f *.log |
| | | |
| | | distclean: clean |
| | | @rm -f tags cscope* |
| | | |
| | | .PHONY: clean entry |
New file |
| | |
| | | |
| | | [section1] |
| | | key1 = 15 |
| | | key2 = hello |
| | | |
| | | |
| | | [section2] |
| | | key1 = 30 |
| | | key2 = world |
| | | |
| | | |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: tpdud.c |
| | | * Description: This file |
| | | * |
| | | * Version: 1.0.0(10/30/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "10/30/2012 01:15:18 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include <unistd.h> |
| | | #include <getopt.h> |
| | | #include <libgen.h> |
| | | |
| | | #include "cp_common.h" |
| | | #include "cp_network.h" |
| | | #include "cp_logger.h" |
| | | #include "cp_proc.h" |
| | | #include "cp_time.h" |
| | | #include "swe_tpdud.h" |
| | | #include "version.h" |
| | | |
| | | static void stop_tpdu_service(SWE_TPDU *tpdu) |
| | | { |
| | | if(!tpdu) |
| | | return ; |
| | | |
| | | log_dbg("release tpdu contex [%p]\n", tpdu); |
| | | |
| | | if( tpdu->dlink ) |
| | | { |
| | | log_nrml("stop tpdu service for downlink socket [%p:%d]\n", tpdu->dlink, tpdu->dlink->fd); |
| | | cp_fds_destroy_sock_clear(tpdu->dlink); |
| | | tpdu->dlink = NULL; |
| | | } |
| | | |
| | | if( tpdu->ulink ) |
| | | { |
| | | log_nrml("stop tpdu service for uplink socket [%p:%d]\n", tpdu->ulink, tpdu->ulink->fd); |
| | | cp_fds_destroy_sock_clear(tpdu->ulink); |
| | | tpdu->ulink = NULL; |
| | | } |
| | | |
| | | t_free(tpdu); |
| | | } |
| | | |
| | | int proc_uplink_event(CP_SOCK *ulink) |
| | | { |
| | | int rv; |
| | | CP_SOCK *dlink = NULL; |
| | | SWE_TPDU *tpdu = NULL; |
| | | |
| | | if(!ulink || !(tpdu=ulink->privt) || !(dlink=tpdu->dlink)) |
| | | { |
| | | log_err("tpdu address:[%p] ulink address:[%p] dlink address:[%p]\n", tpdu, ulink, dlink); |
| | | return -1; |
| | | } |
| | | |
| | | if(ulink->status == SOCK_STAT_DISCONNECT) |
| | | { |
| | | goto stop_service; |
| | | } |
| | | |
| | | if(ulink->event.events & CP_SOCK_EVENT_READ) |
| | | { |
| | | rv = cp_sock_recv(ulink); |
| | | if( 0==rv ) |
| | | { |
| | | log_warn("Socket [%d %s:%d] remote socket [%s:%d] disconnect, remove it now\n", |
| | | ulink->fd, ulink->laddr, ulink->lport, ulink->raddr, ulink->rport); |
| | | goto stop_service; |
| | | } |
| | | else if(rv > 0) |
| | | { |
| | | log_nrml("Socket [%d %s:%d] receive %d bytes data:\n", ulink->fd, ulink->laddr, ulink->lport, rv); |
| | | cp_log_dump(LOG_LEVEL_DEBUG, ulink->rbuf->data, ulink->rbuf->len); |
| | | |
| | | if(ulink->rbuf->len > 0) |
| | | { |
| | | cp_string_move(dlink->sbuf, ulink->rbuf); |
| | | cp_sock_send(dlink); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | log_err("Socket [%d %s:%d] receive data failed: %s\n", ulink->fd, ulink->laddr, ulink->lport, strerror(errno)); |
| | | } |
| | | } |
| | | else if(ulink->event.events & CP_SOCK_EVENT_IDLE_TIMEOUT) |
| | | { |
| | | log_warn("uplink socket [%d] is idle and to-do something here\n"); |
| | | } |
| | | else if(ulink->event.events & CP_SOCK_EVENT_MSG_TIMEOUT) |
| | | { |
| | | log_warn("uplink socket [%d] message is timeout and to-do something here\n"); |
| | | } |
| | | |
| | | |
| | | |
| | | return 0; |
| | | |
| | | stop_service: |
| | | stop_tpdu_service(tpdu); |
| | | return 0; |
| | | } |
| | | |
| | | /* Connect to hostsim */ |
| | | int tpdu_connect_uplink(SWE_TPDU *tpdu) |
| | | { |
| | | CP_SOCK *ulink; |
| | | CP_SOCK *dlink; |
| | | |
| | | if(!tpdu || !(dlink=tpdu->dlink)) |
| | | { |
| | | log_err("tpdu address [%p] dlink address [%p]\n", tpdu, dlink); |
| | | return -1; |
| | | } |
| | | |
| | | ulink = tpdu->ulink; |
| | | |
| | | ulink=cp_sock_connect_regist(dlink->fds, ulink, tpdu->raddr, tpdu->rport, 0, proc_uplink_event); |
| | | if( !ulink ) /* connect failure */ |
| | | { |
| | | /* the uplink connect failure or connect already, then we should |
| | | * remove the downlink socket from task list */ |
| | | log_err("connect to remote [%s:%d] failure\n", tpdu->raddr, tpdu->rport); |
| | | tpdu->ulink = NULL; |
| | | return -1; |
| | | } |
| | | else /* connecting in progress */ |
| | | { |
| | | ulink->privt = tpdu; |
| | | tpdu->ulink = ulink; |
| | | log_info("connect to remote [%s:%d] in progress\n", tpdu->raddr, tpdu->rport); |
| | | cp_fds_add_sock_task(dlink); |
| | | dlink->event.events = 0; /* clear the events flag */ |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int tpdu_service_route(CP_SOCK *dlink) |
| | | { |
| | | int rv = 0; |
| | | |
| | | SWE_TPDU *tpdu; |
| | | |
| | | if( !dlink ) |
| | | return -1; |
| | | |
| | | tpdu = dlink->privt; |
| | | |
| | | /* If it's first data incoming from the dlink, then we should |
| | | * malloc a TPDU work context now and save it */ |
| | | if( !tpdu ) |
| | | { |
| | | if( !(tpdu=t_malloc(sizeof(*tpdu))) ) |
| | | { |
| | | log_err("Malloc TPDU work contex failure\n"); |
| | | goto stop_service; |
| | | } |
| | | else |
| | | { |
| | | SWE_TPDU *serv_tpdu; |
| | | log_info("malloc TPDU work contex [%p]\n", tpdu); |
| | | |
| | | serv_tpdu = dlink->serv_sock->privt; |
| | | dlink->privt = tpdu; |
| | | tpdu->dlink = dlink; |
| | | strcpy(tpdu->raddr, serv_tpdu->raddr); |
| | | tpdu->rport = serv_tpdu->rport; |
| | | } |
| | | } |
| | | |
| | | log_dbg("Process socket [%d %s:%d] with event [%d]\n", dlink->fd, dlink->laddr, dlink->lport, dlink->event.events); |
| | | |
| | | /* If there is data incoming from this socket, now we receive the data */ |
| | | if(dlink->event.events & CP_SOCK_EVENT_READ) |
| | | { |
| | | rv = cp_sock_recv(dlink); |
| | | if( rv == 0 ) |
| | | { |
| | | log_warn("Socket [%d %s:%d] remote socket [%s:%d] disconnect, remove it now\n", |
| | | dlink->fd, dlink->laddr, dlink->lport, dlink->raddr, dlink->rport); |
| | | goto stop_service; |
| | | } |
| | | else if( rv < 0) |
| | | { |
| | | log_err("Socket [%d %s:%d] receive data failed: %s\n", dlink->fd, dlink->laddr, dlink->lport, strerror(errno)); |
| | | goto stop_service; |
| | | } |
| | | |
| | | /* Receive data OK */ |
| | | log_nrml("Socket [%d %s:%d] receive %d bytes data:\n", dlink->fd, dlink->laddr, dlink->lport, rv); |
| | | cp_log_dump(LOG_LEVEL_DEBUG, dlink->rbuf->data, dlink->rbuf->len); |
| | | } |
| | | else if(dlink->event.events & CP_SOCK_EVENT_HUP) |
| | | { |
| | | log_warn("socket [%d] remote already disconnect\n", dlink->fd); |
| | | dlink->status = SOCK_STAT_DISCONNECT; |
| | | goto stop_service; |
| | | } |
| | | else if(dlink->event.events & CP_SOCK_EVENT_IDLE_TIMEOUT) |
| | | { |
| | | log_warn("socket [%d] is idle and to-do something here\n"); |
| | | } |
| | | else if(dlink->event.events & CP_SOCK_EVENT_MSG_TIMEOUT) |
| | | { |
| | | log_warn("socket [%d] message is timeout and to-do something here\n"); |
| | | } |
| | | |
| | | /* If we have receive some data already, now we need do TPDU parser to |
| | | * get the remote server address and port */ |
| | | if( dlink->rbuf->len > 0) |
| | | { |
| | | SWE_TPDU *arg = dlink->serv_sock->privt; |
| | | /* To-Do: parser downlink data here and get the uplink IP address and port */ |
| | | tpdu->rport = arg->rport; |
| | | strncpy(tpdu->raddr, arg->raddr, sizeof(tpdu->raddr)); |
| | | } |
| | | |
| | | /* If not connect to the remote host or it's still connecting, then we do it again */ |
| | | if( !tpdu->ulink || (tpdu->ulink->status==SOCK_STAT_CONNECTING)) |
| | | { |
| | | log_nrml("tpdu dlink: %p\n", tpdu->dlink); |
| | | if( tpdu_connect_uplink(tpdu) < 0 ) |
| | | goto stop_service; |
| | | } |
| | | |
| | | /* If connect to the remote host already, now we send the data to the remote host */ |
| | | if( !tpdu->ulink || (tpdu->ulink->status==SOCK_STAT_CONNECTED)) |
| | | { |
| | | log_dbg("connect to remote [%s:%d] ok and send %d bytes data\n", tpdu->raddr, tpdu->rport, dlink->rbuf->len); |
| | | cp_fds_del_sock_task(dlink); |
| | | if(dlink->rbuf->len > 0) |
| | | { |
| | | cp_string_move(tpdu->ulink->sbuf, dlink->rbuf); |
| | | cp_sock_send(tpdu->ulink); /* send the data to the remote host */ |
| | | return 0; |
| | | } |
| | | } |
| | | |
| | | return 0; |
| | | |
| | | stop_service: |
| | | stop_tpdu_service(tpdu); |
| | | tpdu = NULL; |
| | | return 0; |
| | | } |
| | | |
| | | void print_usage(char *progname) |
| | | { |
| | | version(progname); |
| | | printf("Usage: %s [OPTION]...\n", progname); |
| | | printf(" %s is a handle program to create a tunnel between an incoming and outgoing FD\n", progname); |
| | | |
| | | printf("\nMandatory arguments to long options are mandatory for short options too:\n"); |
| | | |
| | | printf(" -l[loglevel] To configure the logger level [0(DIS)...8(MAX)], default 4[NRML]\n"); |
| | | printf(" -p[port ] To configure the listening port, default [%d]\n", TPDUD_PORT); |
| | | printf(" -i[RemoteIP] To configure the remote/outgoing IP, default [%s]\n", HOSTSIM_IP); |
| | | printf(" -o[outgoing] To configure the remote/outgoing Port, default [%d]\n", HOSTSIM_PORT); |
| | | printf(" -h[help ] Display this help information\n"); |
| | | printf(" -v[version ] Display the program version\n"); |
| | | printf("\n"); |
| | | |
| | | return ; |
| | | } |
| | | |
| | | |
| | | /******************************************************************************** |
| | | * Description: |
| | | * Input Args: |
| | | * Output Args: |
| | | * Return Value: |
| | | ********************************************************************************/ |
| | | int main (int argc, char **argv) |
| | | { |
| | | CP_FDS *fds; |
| | | CP_SOCK *sock; |
| | | SWE_TPDU tpdu = {.lport=TPDUD_PORT, .raddr=HOSTSIM_IP, .rport=HOSTSIM_PORT}; |
| | | int opt; |
| | | int loglevel = LOG_LEVEL_NRML; |
| | | |
| | | struct option long_options[] = |
| | | { |
| | | {"loglevel", required_argument, NULL, 'l'}, |
| | | {"port", required_argument, NULL, 'p'}, |
| | | {"host", required_argument, NULL, 'i'}, |
| | | {"outgoing", required_argument, NULL, 'o'}, |
| | | {"version", no_argument, NULL, 'v'}, |
| | | {"help", no_argument, NULL, 'h'}, |
| | | {NULL, 0, NULL, 0} |
| | | }; |
| | | |
| | | while ((opt = getopt_long(argc, argv, "l:p:i:o:vh", long_options, NULL)) != -1) |
| | | { |
| | | switch (opt) |
| | | { |
| | | case 'l': |
| | | loglevel = atoi(optarg); |
| | | break; |
| | | |
| | | case 'p': |
| | | tpdu.lport = atoi(optarg); |
| | | break; |
| | | |
| | | case 'i': |
| | | strncpy(tpdu.raddr, optarg, sizeof(tpdu.raddr)); |
| | | break; |
| | | |
| | | case 'o': |
| | | tpdu.rport = atoi(optarg); |
| | | break; |
| | | |
| | | case 'v': |
| | | version(basename(argv[0])); |
| | | return EXIT_SUCCESS; |
| | | |
| | | case 'h': |
| | | print_usage(basename(argv[0])); |
| | | return EXIT_SUCCESS; |
| | | |
| | | default: |
| | | break; |
| | | } |
| | | } |
| | | |
| | | //if (!cp_log_init(NULL, "tpdud.log", LOG_LEVEL_MAX, LOG_ROLLBACK_NONE) || cp_log_open()) |
| | | //if (!cp_log_init(NULL, "tpdud.log", loglevel, LOG_ROLLBACK_SIZE) || cp_log_open()) |
| | | if (!cp_log_init(NULL, DBG_LOG_FILE, LOG_LEVEL_MAX, LOG_ROLLBACK_NONE) || cp_log_open()) |
| | | //if (!cp_log_init(NULL, DBG_LOG_FILE, loglevel, LOG_ROLLBACK_NONE) || cp_log_open()) |
| | | goto cleanup; |
| | | |
| | | cp_install_proc_signal(); |
| | | |
| | | if( !(fds=cp_fds_init(NULL, CP_DEF_MAX_EVENTS, CP_DEF_FDS_TIMEOUT)) ) |
| | | goto cleanup; |
| | | |
| | | if( !(sock=cp_sock_server_regist(fds, NULL, tpdu.lport, 0, tpdu_service_route, (void *)&tpdu)) ) |
| | | goto cleanup; |
| | | |
| | | while( !g_cp_signal.stop ) |
| | | { |
| | | cp_fds_detect_event(fds); |
| | | cp_fds_proc_event(fds); |
| | | cp_sock_detect_timeout(fds); |
| | | micro_second_sleep(10); |
| | | } |
| | | |
| | | cleanup: |
| | | cp_sock_term_all_service_clear(fds); |
| | | cp_log_term(); |
| | | return 0; |
| | | } /* ----- End of main() ----- */ |
| | | |
| | | |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: tpdud.h |
| | | * Description: This head file |
| | | * |
| | | * Version: 1.0.0(11/19/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "11/19/2012 11:21:05 AM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #ifndef __SWE_TPDUD_H |
| | | #define __SWE_TPDUD_H |
| | | |
| | | #include <cp_sock.h> |
| | | |
| | | #define HOSTSIM_PORT 9002 |
| | | #define HOSTSIM_IP "192.168.3.6" |
| | | |
| | | #define TPDUD_PORT 8000 |
| | | #define UPLINK_ADDR HOSTSIM_IP |
| | | #define UPLINK_PORT HOSTSIM_PORT |
| | | |
| | | #define FLAG_TPDU_INIT (1<<0) |
| | | #define FLAG_TPDU_STOP (1<<7) |
| | | |
| | | typedef struct _SWE_TPDU |
| | | { |
| | | unsigned char flag; |
| | | char raddr[32]; /* uplink remote listen port */ |
| | | int lport; /* dlink local listen port */ |
| | | int rport; /* uplink remote IP address */ |
| | | |
| | | CP_SOCK *dlink; /* listen port accept socket */ |
| | | CP_SOCK *ulink; /* connect to hostsim socket */ |
| | | } SWE_TPDU; |
| | | |
| | | |
| | | #endif |
| | | |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: test_array.c |
| | | * Description: This file used to test the array library |
| | | * |
| | | * Version: 1.0.0(08/14/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "08/14/2012 05:17:03 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include <stdio.h> |
| | | #include <string.h> |
| | | #include <stdlib.h> |
| | | |
| | | #include "cp_array.h" |
| | | #include "cp_sock.h" |
| | | #include "cp_logger.h" |
| | | |
| | | #define MAX_ITEMS 10 |
| | | |
| | | /******************************************************************************** |
| | | * Description: |
| | | * Input Args: |
| | | * Output Args: |
| | | * Return Value: |
| | | ********************************************************************************/ |
| | | int main (int argc, char **argv) |
| | | { |
| | | int i; |
| | | |
| | | CP_SOCK *sock = NULL; |
| | | CP_SOCK *tmp = NULL; |
| | | CP_ARRAY *array = NULL; |
| | | |
| | | if (!cp_log_init(NULL, DBG_LOG_FILE, LOG_LEVEL_MAX, LOG_ROLLBACK_NONE) || cp_log_open()) |
| | | return 0; |
| | | |
| | | if( !(array=cp_array_init(NULL, MAX_ITEMS)) ) |
| | | return -1; |
| | | |
| | | for (i=0; i<MAX_ITEMS; i++) |
| | | { |
| | | sock = cp_sock_init(NULL, 1024, 1024, 10, 30); |
| | | if( cp_array_add(array, sock)<0 ) |
| | | { |
| | | cp_sock_term(sock); |
| | | } |
| | | else |
| | | { |
| | | if(i==3) |
| | | { |
| | | tmp = sock; |
| | | } |
| | | } |
| | | } |
| | | |
| | | printf("Array usage %d/%d \n", cp_array_count(array), cp_array_size(array)); |
| | | |
| | | cp_array_travel(array); |
| | | |
| | | if( !cp_array_rm_bydata(array, tmp) ) |
| | | { |
| | | printf("remove and terminate sock [%p] from array\n", tmp); |
| | | cp_sock_term(tmp); |
| | | } |
| | | cp_array_travel(array); |
| | | |
| | | cp_list_array_for_each(array, i, sock) |
| | | { |
| | | cp_sock_term(sock); |
| | | } |
| | | |
| | | cp_array_term(array); |
| | | cp_log_term(); |
| | | |
| | | return 0; |
| | | |
| | | } /* ----- End of main() ----- */ |
| | | |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: test_hal.c |
| | | * Description: This file |
| | | * |
| | | * Version: 1.0.0(12/05/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "12/05/2012 04:52:59 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include <libgen.h> |
| | | #include <getopt.h> |
| | | #include "cp_hal.h" |
| | | |
| | | #define HAL_LIBRARY_TEST |
| | | |
| | | void test_led_hal_api(void) |
| | | { |
| | | printf("+------------------------------------+\n"); |
| | | printf("| Test LED HAL API |\n"); |
| | | printf("+------------------------------------+\n"); |
| | | |
| | | printf("Turn all LED off\n"); |
| | | hal_turn_led_off(LED_ALL); |
| | | sleep(2); |
| | | |
| | | printf("Turn LED blink one by one\n"); |
| | | hal_turn_led_blink(LED_SYS, MODE_FAST); |
| | | hal_turn_led_blink(LED_SIM1, MODE_FAST); |
| | | hal_turn_led_blink(LED_SIM2, MODE_FAST); |
| | | hal_turn_led_blink(LED_WIFI, MODE_FAST); |
| | | hal_turn_led_blink(LED_ETH, MODE_FAST); |
| | | sleep(4); |
| | | |
| | | printf("Turn LED off one by one\n"); |
| | | hal_turn_led_off(LED_SYS); |
| | | hal_turn_led_off(LED_SIM1); |
| | | hal_turn_led_off(LED_SIM2); |
| | | hal_turn_led_off(LED_WIFI); |
| | | hal_turn_led_off(LED_ETH); |
| | | sleep(4); |
| | | |
| | | printf("Turn LED on one by one\n"); |
| | | hal_turn_led_on(LED_SYS); |
| | | hal_turn_led_on(LED_SIM1); |
| | | hal_turn_led_on(LED_SIM2); |
| | | hal_turn_led_on(LED_WIFI); |
| | | hal_turn_led_on(LED_ETH); |
| | | sleep(4); |
| | | |
| | | printf("Turn all LED off\n"); |
| | | hal_turn_led_off(LED_ALL); |
| | | sleep(2); |
| | | |
| | | printf("Turn all LED blink\n"); |
| | | hal_turn_led_blink(LED_ALL, MODE_SLOW); |
| | | sleep(4); |
| | | |
| | | printf("Turn all LED on\n"); |
| | | hal_turn_led_on(LED_ALL); |
| | | sleep(4); |
| | | hal_turn_led_off(LED_ALL); |
| | | } |
| | | |
| | | void test_buzzer_hal_api(void) |
| | | { |
| | | printf("+------------------------------------+\n"); |
| | | printf("| Test Buzzer HAL API |\n"); |
| | | printf("+------------------------------------+\n"); |
| | | |
| | | printf("Turn buzzer on\n"); |
| | | hal_turn_buzzer_on(); |
| | | sleep(2); |
| | | |
| | | printf("Turn buzzer off\n"); |
| | | hal_turn_buzzer_off(); |
| | | sleep(2); |
| | | |
| | | printf("Turn buzzer beep for 5 times\n"); |
| | | hal_turn_buzzer_beep(3); |
| | | sleep(4); |
| | | |
| | | printf("Turn buzzer off\n"); |
| | | hal_turn_buzzer_off(); |
| | | sleep(3); |
| | | |
| | | printf("Turn buzzer beep infinitely\n"); |
| | | hal_turn_buzzer_beep(0); |
| | | sleep(5); |
| | | |
| | | printf("Turn buzzer off\n"); |
| | | hal_turn_buzzer_off(); |
| | | } |
| | | |
| | | void test_gprs_hal_api(void) |
| | | { |
| | | int rv = 0; |
| | | |
| | | printf("+------------------------------------+\n"); |
| | | printf("| Test GPRS HAL API |\n"); |
| | | printf("+------------------------------------+\n"); |
| | | |
| | | hal_poweron_gprs(SIM_NONE); |
| | | |
| | | rv = hal_check_simdoor(SIM_ALL); |
| | | printf("Check all SIM card present status: 0x%02x\n", rv); |
| | | |
| | | rv = hal_check_simdoor(SIM1); |
| | | printf("Check SIM1 card present status: 0x%02x\n", rv); |
| | | |
| | | rv = hal_check_simdoor(SIM2); |
| | | printf("Check SIM2 card present status: 0x%02x\n", rv); |
| | | |
| | | printf("Get current working SIM card: 0x%02x\n", hal_get_worksim()); |
| | | |
| | | hal_set_worksim(SIM2); |
| | | printf("Set current working SIM to SIM2\n"); |
| | | |
| | | printf("Get current working SIM card: 0x%02x\n", hal_get_worksim()); |
| | | |
| | | hal_set_worksim(SIM1); |
| | | printf("Set current working SIM to SIM1\n"); |
| | | |
| | | printf("Get current working SIM card: 0x%02x\n", hal_get_worksim()); |
| | | hal_poweroff_gprs(); |
| | | |
| | | } |
| | | |
| | | void print_usage(char *progname) |
| | | { |
| | | printf("Usage: %s [OPTION]...\n", progname); |
| | | printf("\nMandatory arguments to long options are mandatory for short options too:\n"); |
| | | |
| | | printf(" -l[led ] Test LED HAL API\n"); |
| | | printf(" -b[buzzer ] Test Buzzer HAL API\n"); |
| | | printf(" -g[gprs ] Test GPRS HAL API\n"); |
| | | printf(" -h[help ] Display this help information\n"); |
| | | |
| | | |
| | | } |
| | | |
| | | |
| | | #ifdef HAL_LIBRARY_TEST |
| | | /******************************************************************************** |
| | | * Description: |
| | | * Input Args: |
| | | * Output Args: |
| | | * Return Value: |
| | | ********************************************************************************/ |
| | | int main (int argc, char **argv) |
| | | { |
| | | int opt; |
| | | char *progname=NULL; |
| | | int test_led = 0; |
| | | int test_gprs = 0; |
| | | int test_buzzer = 0; |
| | | |
| | | struct option long_options[] = { |
| | | {"led", no_argument, NULL, 'l'}, |
| | | {"buzzer", no_argument, NULL, 'b'}, |
| | | {"gprs", no_argument, NULL, 'g'}, |
| | | {"help", no_argument, NULL, 'h'}, |
| | | {NULL, 0, NULL, 0} |
| | | }; |
| | | |
| | | progname = basename(argv[0]); |
| | | |
| | | while ((opt = getopt_long(argc, argv, "bghl", long_options, NULL)) != -1) |
| | | { |
| | | switch(opt) |
| | | { |
| | | case 'b': |
| | | test_buzzer = 1; |
| | | break; |
| | | |
| | | case 'l': |
| | | test_led = 1; |
| | | break; |
| | | |
| | | case 'g': |
| | | test_gprs = 1; |
| | | break; |
| | | |
| | | case 'h': |
| | | print_usage(progname); |
| | | |
| | | default: |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if(!test_buzzer && !test_led && !test_gprs) |
| | | print_usage(progname); |
| | | |
| | | if(test_buzzer) |
| | | test_buzzer_hal_api(); |
| | | |
| | | if(test_led) |
| | | test_led_hal_api(); |
| | | |
| | | if(test_gprs) |
| | | test_gprs_hal_api(); |
| | | |
| | | return 0; |
| | | } /* ----- End of main() ----- */ |
| | | |
| | | #endif /* HAL_LIBRARY_TEST */ |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2013 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: test_hh.c |
| | | * Description: This file |
| | | * |
| | | * Version: 1.0.0(01/28/2013~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "01/28/2013 03:35:36 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include <libgen.h> |
| | | #include "cp_comport.h" |
| | | #define HH_DATAPORT "/dev/ttySSHHR" |
| | | |
| | | /******************************************************************************** |
| | | * Description: |
| | | * Input Args: |
| | | * Output Args: |
| | | * Return Value: |
| | | ********************************************************************************/ |
| | | int main (int argc, char **argv) |
| | | { |
| | | int i; |
| | | COM_PORT *comport = NULL; |
| | | unsigned char sbuf[10]={0x02, 0x48, 0x32, 0x03, 0x20, 0x00, 0x00, 0xF6, 0xBE, 0x03}; |
| | | unsigned char rbuf[10]; |
| | | #if 0 |
| | | char *HH_DATAPORT = NULL; |
| | | |
| | | if(argc != 2) |
| | | { |
| | | printf("Usage: %s [device name]\n", basename(argv[0])); |
| | | return 0; |
| | | } |
| | | HH_DATAPORT = argv[1]; |
| | | #endif |
| | | |
| | | if( !(comport=comport_init(HH_DATAPORT, 115200, "8N1N")) ) |
| | | { |
| | | printf("Initialise comport %s failure\n", HH_DATAPORT); |
| | | return -1; |
| | | } |
| | | |
| | | if(comport_open(comport)<0) |
| | | { |
| | | printf("Open comport %s failure\n", HH_DATAPORT); |
| | | return -1; |
| | | } |
| | | |
| | | if(comport_send(comport, (char *)sbuf, sizeof(sbuf)) < 0) |
| | | { |
| | | printf("Send 10 bytes data to %s failure\n", HH_DATAPORT); |
| | | return -1; |
| | | } |
| | | printf("Send %d bytes data to %s:\n>>", sizeof(sbuf), HH_DATAPORT); |
| | | for(i=0; i<10; i++) |
| | | { |
| | | printf("%02x ", sbuf[i]); |
| | | } |
| | | printf("\n"); |
| | | |
| | | |
| | | memset(rbuf, 0, sizeof(rbuf)); |
| | | if((i=comport_recv(comport, (char *)rbuf, sizeof(rbuf), 5000)) < 0) |
| | | { |
| | | printf("Receive 10 bytes data to %s failure\n", HH_DATAPORT); |
| | | return -1; |
| | | } |
| | | |
| | | printf("Receive %d bytes data from %s:\n<<", i, HH_DATAPORT); |
| | | for(i=0; i<10; i++) |
| | | { |
| | | printf("%02x ", rbuf[i]); |
| | | } |
| | | printf("\n"); |
| | | |
| | | comport_term(comport); |
| | | |
| | | return 0; |
| | | } /* ----- End of main() ----- */ |
| | | |
| | | |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: test_ini.c |
| | | * Description: This file |
| | | * |
| | | * Version: 1.0.0(12/18/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "12/18/2012 10:54:09 AM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include "cp_iniparser.h" |
| | | |
| | | |
| | | #define INI_CONF "sample.ini" |
| | | |
| | | /******************************************************************************** |
| | | * Description: |
| | | * Input Args: |
| | | * Output Args: |
| | | * Return Value: |
| | | ********************************************************************************/ |
| | | int main (int argc, char **argv) |
| | | { |
| | | dictionary *ini; |
| | | FILE *fp; |
| | | |
| | | ini=iniparser_load(INI_CONF); |
| | | |
| | | fp=fopen(INI_CONF, "w+"); |
| | | |
| | | iniparser_set(ini, "section1:key1", "30"); |
| | | |
| | | |
| | | iniparser_dump(ini, stderr); |
| | | |
| | | iniparser_dump_ini(ini, fp); |
| | | |
| | | |
| | | iniparser_freedict(ini); |
| | | |
| | | |
| | | return 0; |
| | | } /* ----- End of main() ----- */ |
| | | |
| | | |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: test_klist.c |
| | | * Description: This file is for test kernel space double linked list. |
| | | * |
| | | * Version: 1.0.0(11/12/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "11/12/2012 04:26:39 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include "cp_klist.h" |
| | | #include "cp_sock.h" |
| | | |
| | | //#define LIST_REVERSE |
| | | |
| | | void travel_list(struct list_head *head) |
| | | { |
| | | CP_SOCK *sock, *tsock; |
| | | |
| | | |
| | | if( (sock=cp_sock_init(NULL, CP_SOCK_RCVBUF, CP_SOCK_SNDBUF, CP_SOCK_KEEPINTVL, CP_SOCK_KEEPCNT)) ) |
| | | { |
| | | list_add_tail(&sock->rlist, head); |
| | | printf("Add new socket %p to sock_list \n", sock); |
| | | } |
| | | |
| | | /* Use list_for_each_entry to travel the socket list, we can not remove the node in it */ |
| | | list_for_each_entry_safe(sock, tsock, head, rlist) |
| | | { |
| | | printf("Travel2 socket list on socket %p\n", sock); |
| | | } |
| | | } |
| | | |
| | | |
| | | /******************************************************************************** |
| | | * Description: |
| | | * Input Args: |
| | | * Output Args: |
| | | * Return Value: |
| | | ********************************************************************************/ |
| | | int main (int argc, char **argv) |
| | | { |
| | | int i; |
| | | struct list_head sock_list; |
| | | CP_SOCK *sock, *tsock; |
| | | |
| | | INIT_LIST_HEAD(&sock_list); |
| | | |
| | | for(i=0; i<10; i++) |
| | | { |
| | | if( (sock=cp_sock_init(NULL, CP_SOCK_RCVBUF, CP_SOCK_SNDBUF, CP_SOCK_KEEPINTVL, CP_SOCK_KEEPCNT)) ) |
| | | { |
| | | list_add_tail(&sock->rlist, &sock_list); |
| | | printf("Add socket %p to sock_list \n", sock); |
| | | } |
| | | } |
| | | |
| | | /* Use list_for_each_entry to travel the socket list, we can not remove the node in it */ |
| | | list_for_each_entry(sock, &sock_list, rlist) |
| | | { |
| | | printf("Travel socket list on socket %p\n", sock); |
| | | } |
| | | |
| | | travel_list(&sock_list); |
| | | |
| | | /* Use list_for_each_entry_safe to travel the socket list and destroy the socket */ |
| | | list_for_each_entry_safe(sock, tsock, &sock_list, rlist) |
| | | { |
| | | list_del(&sock->rlist); |
| | | cp_sock_term(sock); |
| | | printf("Remove and destroy socket %p from socket list\n", sock); |
| | | } |
| | | |
| | | return 0; |
| | | } /* ----- End of main() ----- */ |
| | | |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue <guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: test_logger.c |
| | | * Description: This is the linux logger system test code. |
| | | * |
| | | * Version: 1.0.0(08/08/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "08/08/2012 06:51:40 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include <unistd.h> |
| | | #include <stdio.h> |
| | | #include <string.h> |
| | | #include <libgen.h> |
| | | #include "cp_logger.h" |
| | | |
| | | |
| | | /******************************************************************************** |
| | | * Description: |
| | | * Input Args: |
| | | * Output Args: |
| | | * Return Value: |
| | | ********************************************************************************/ |
| | | int main (int argc, char **argv) |
| | | { |
| | | char buf[30]="Hello World!\n"; |
| | | char file[FILENAME_LEN]; |
| | | |
| | | snprintf(file, FILENAME_LEN, "%s.log", basename(argv[0]) ); |
| | | |
| | | //if (! cp_log_init(NULL, DBG_LOG_FILE, LOG_LEVEL_NRML, LOG_ROLLBACK_NONE) ) |
| | | //if (! cp_log_init(NULL, DEFAULT_LOGFILE, LOG_LEVEL_MAX, LOG_ROLLBACK_SIZE) ) |
| | | if(! cp_log_init(NULL, file, LOG_LEVEL_MAX, 12) || cp_log_open() ) |
| | | return 0; |
| | | |
| | | |
| | | while(1) |
| | | { |
| | | log_info("1connection.\n"); |
| | | log_dbg("2connection.\n"); |
| | | log_nrml("3connection.\n"); |
| | | log_warn("4connection.\n"); |
| | | log_err("5connection.\n"); |
| | | log_fatal("6connection.\n"); |
| | | |
| | | cp_log_dump(LOG_LEVEL_DEBUG, buf, 30); |
| | | |
| | | sleep(1); |
| | | } |
| | | |
| | | cp_log_term(); |
| | | |
| | | return 0; |
| | | } /* ----- End of main() ----- */ |
| | | |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: test_queue.c |
| | | * Description: This file used to test the queue library |
| | | * |
| | | * Version: 1.0.0(08/14/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "08/14/2012 05:17:03 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include <stdio.h> |
| | | #include <string.h> |
| | | #include <stdlib.h> |
| | | |
| | | #include "cp_queue.h" |
| | | #include "cp_sock.h" |
| | | |
| | | #define MAX_ITEMS 10 |
| | | |
| | | /******************************************************************************** |
| | | * Description: |
| | | * Input Args: |
| | | * Output Args: |
| | | * Return Value: |
| | | ********************************************************************************/ |
| | | int main (int argc, char **argv) |
| | | { |
| | | int i; |
| | | |
| | | CP_SOCK *sock = NULL; |
| | | CP_SOCK *tmp = NULL; |
| | | |
| | | CP_QUEUE *queue = NULL; |
| | | |
| | | queue = cp_queue_init(NULL, MAX_ITEMS); |
| | | |
| | | //for (i=0; i<MAX_ITEMS; i++) |
| | | for (i=0; i<MAX_ITEMS+10; i++) |
| | | //for (i=0; i<MAX_ITEMS-3; i++) |
| | | { |
| | | sock = cp_sock_init(NULL, 1024, 1024, 10, 30); |
| | | if( NULL==cp_enqueue(queue, sock) ) |
| | | { |
| | | cp_sock_term(sock); |
| | | } |
| | | else |
| | | { |
| | | if(i==3) |
| | | { |
| | | tmp = sock; |
| | | } |
| | | printf("enqueue sock %p\n", sock); |
| | | } |
| | | } |
| | | |
| | | |
| | | printf("queue usage %d/%d \n", cp_queue_count(queue), cp_queue_size(queue)); |
| | | |
| | | cp_travel_queue(queue); |
| | | if( cp_rmqueue(queue, tmp) ) |
| | | { |
| | | printf("remove and terminate sock [%p] from queue\n", tmp); |
| | | cp_sock_term(tmp); |
| | | } |
| | | cp_travel_queue(queue); |
| | | |
| | | while(!cp_queue_is_empty(queue)) |
| | | { |
| | | if( (sock=cp_dequeue(queue)) ) |
| | | { |
| | | printf("Terminate socket: %p\n", sock); |
| | | cp_sock_term(sock); |
| | | } |
| | | } |
| | | |
| | | cp_queue_destroy(queue); |
| | | |
| | | return 0; |
| | | |
| | | } /* ----- End of main() ----- */ |
| | | |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: test_client_sock.c |
| | | * Description: This file |
| | | * |
| | | * Version: 1.0.0(10/30/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "10/30/2012 01:15:18 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include "cp_network.h" |
| | | #include "cp_logger.h" |
| | | #include "cp_proc.h" |
| | | #include "cp_time.h" |
| | | |
| | | |
| | | //#define SERV_ADDR "192.168.1.175" |
| | | #define SERV_ADDR "192.168.1.78" |
| | | //#define SERV_ADDR "kkernel.oicp.net" |
| | | #define SERV_PORT 8880 |
| | | |
| | | int service_route(CP_SOCK *sock) |
| | | { |
| | | int rv; |
| | | |
| | | if( !sock ) |
| | | return -1; |
| | | |
| | | printf("Client socket [%d] get event: %d\n", sock->fd, sock->event.events); |
| | | if(sock->event.events & EPOLLIN) |
| | | { |
| | | rv = cp_sock_recv(sock); |
| | | if(!rv) |
| | | { |
| | | log_nrml("Socket [%d %s:%d] remote socket [%s:%d] disconnect, remove it now\n", |
| | | sock->fd, sock->laddr, sock->lport, sock->raddr, sock->rport); |
| | | |
| | | cp_fds_destroy_sock(sock); |
| | | g_cp_signal.stop = 1; |
| | | |
| | | return 0; |
| | | } |
| | | else if(rv > 0) |
| | | { |
| | | log_nrml("Socket [%d %s:%d] receive [%d] bytes data:\n", sock->fd, sock->laddr, sock->lport, sock->rbuf->len); |
| | | cp_log_dump(LOG_LEVEL_DEBUG, sock->rbuf->data, sock->rbuf->len); |
| | | cp_string_clear_data(sock->rbuf); |
| | | } |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | /******************************************************************************** |
| | | * Description: |
| | | * Input Args: |
| | | * Output Args: |
| | | * Return Value: |
| | | ********************************************************************************/ |
| | | int main (int argc, char **argv) |
| | | { |
| | | CP_FDS *fds; |
| | | CP_SOCK *sock = NULL; |
| | | |
| | | if ( !cp_log_init(NULL, DBG_LOG_FILE, LOG_LEVEL_NRML, LOG_ROLLBACK_NONE) || cp_log_open() ) |
| | | //if ( !cp_log_init(NULL, DBG_LOG_FILE, LOG_LEVEL_MAX, LOG_ROLLBACK_NONE) || cp_log_open() ) |
| | | return -1; |
| | | |
| | | cp_install_proc_signal(); |
| | | |
| | | if( !(fds=cp_fds_init(NULL, CP_DEF_MAX_EVENTS, CP_DEF_FDS_TIMEOUT)) ) |
| | | return -2; |
| | | |
| | | while( !g_cp_signal.stop ) |
| | | { |
| | | sock = cp_sock_connect_regist(fds, sock, SERV_ADDR, SERV_PORT, 0, service_route); |
| | | if( sock && sock->status==SOCK_STAT_CONNECTING) |
| | | { |
| | | /* Connect is in progress */ |
| | | sleep(1); |
| | | continue; |
| | | } |
| | | else if(!sock || sock->status!=SOCK_STAT_CONNECTED) |
| | | { |
| | | break; |
| | | } |
| | | |
| | | cp_string_cstrcpy(sock->sbuf, "Hello World!\n"); |
| | | printf("Send buffer data: %s", cp_string_data(sock->sbuf)); |
| | | cp_sock_send(sock); |
| | | |
| | | cp_fds_detect_event(fds); |
| | | |
| | | cp_fds_proc_event(fds); |
| | | |
| | | micro_second_sleep(100); |
| | | } |
| | | |
| | | cp_sock_term_all_service_clear(fds); |
| | | |
| | | cp_log_term(); |
| | | |
| | | return 0; |
| | | } /* ----- End of main() ----- */ |
| | | |
| | | |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: test_sock_server.c |
| | | * Description: This file |
| | | * |
| | | * Version: 1.0.0(10/30/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "10/30/2012 01:15:18 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include "cp_network.h" |
| | | #include "cp_logger.h" |
| | | #include "cp_proc.h" |
| | | #include "cp_time.h" |
| | | |
| | | |
| | | #define SERV_PORT1 8880 |
| | | #define SERV_PORT2 8881 |
| | | |
| | | #define DOMAIN "kkernel.oicp.net" |
| | | #define IPADDR "192.168.1.78" |
| | | |
| | | int service_route(CP_SOCK *sock) |
| | | { |
| | | int rv = 0; |
| | | log_nrml("Process socket [%d %s:%d] get event [%d]\n", sock->fd, sock->laddr, sock->lport, sock->event.events); |
| | | |
| | | if(sock->event.events & EPOLLIN) |
| | | { |
| | | rv = cp_sock_recv(sock); |
| | | if(0==rv) |
| | | { |
| | | log_nrml("Socket [%d %s:%d] remote socket [%s:%d] disconnect, remove it now\n", |
| | | sock->fd, sock->laddr, sock->lport, sock->raddr, sock->rport); |
| | | |
| | | cp_fds_destroy_sock(sock); |
| | | |
| | | return 0; |
| | | } |
| | | else if(rv > 0) |
| | | { |
| | | log_nrml("Socket[%d] recv buffer %d bytes data:\n", sock->fd, sock->rbuf->len); |
| | | //cp_log_dump(LOG_LEVEL_NRML, sock->rbuf->data, sock->rbuf->len); |
| | | |
| | | cp_string_move(sock->sbuf, sock->rbuf); |
| | | |
| | | log_nrml("Socket[%d] send buffer %d bytes data:\n", sock->fd, sock->sbuf->len); |
| | | cp_sock_send(sock); |
| | | cp_string_clear_data(sock->sbuf); |
| | | } |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | /******************************************************************************** |
| | | * Description: |
| | | * Input Args: |
| | | * Output Args: |
| | | * Return Value: |
| | | ********************************************************************************/ |
| | | int main (int argc, char **argv) |
| | | { |
| | | CP_FDS *fds; |
| | | CP_SOCK *sock; |
| | | |
| | | //if (!cp_log_init(NULL, DBG_LOG_FILE, LOG_LEVEL_NRML, LOG_ROLLBACK_NONE) || cp_log_open()) |
| | | if (!cp_log_init(NULL, DBG_LOG_FILE, LOG_LEVEL_MAX, LOG_ROLLBACK_NONE) || cp_log_open()) |
| | | goto cleanup; |
| | | |
| | | cp_install_proc_signal(); |
| | | |
| | | if( !(fds=cp_fds_init(NULL, CP_DEF_MAX_EVENTS, CP_DEF_FDS_TIMEOUT)) ) |
| | | goto cleanup; |
| | | |
| | | if( !(sock=cp_sock_server_regist(fds, NULL, SERV_PORT1, 0, service_route, NULL)) ) |
| | | goto cleanup; |
| | | |
| | | if( !(sock=cp_sock_server_regist(fds, NULL, SERV_PORT2, 0, service_route, NULL)) ) |
| | | goto cleanup; |
| | | |
| | | while( !g_cp_signal.stop ) |
| | | { |
| | | cp_fds_detect_event(fds); |
| | | cp_fds_proc_event(fds); |
| | | micro_second_sleep(10); |
| | | } |
| | | |
| | | cleanup: |
| | | cp_sock_term_all_service_clear(fds); |
| | | cp_log_term(); |
| | | return 0; |
| | | } /* ----- End of main() ----- */ |
| | | |
| | | |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: test_string.c |
| | | * Description: This file |
| | | * |
| | | * Version: 1.0.0(11/27/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "11/27/2012 01:28:39 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include <cp_string.h> |
| | | |
| | | |
| | | /******************************************************************************** |
| | | * Description: |
| | | * Input Args: |
| | | * Output Args: |
| | | * Return Value: |
| | | ********************************************************************************/ |
| | | int main (int argc, char **argv) |
| | | { |
| | | int i; |
| | | cp_string *rcv; |
| | | cp_string *snd; |
| | | |
| | | rcv = cp_string_create_empty(64); |
| | | snd = cp_string_create_empty(64); |
| | | |
| | | printf("=======================\n"); |
| | | printf("Test cp_string_copy \n"); |
| | | printf("=======================\n"); |
| | | cp_string_clear_data(rcv); |
| | | cp_string_cstrcpy(rcv, "Hello world!"); |
| | | printf("Receive buffer data:\n"); |
| | | cp_string_dump(rcv); |
| | | |
| | | for(i=0; i<20; i++) |
| | | { |
| | | if( cp_string_copy(snd, rcv) > 0) |
| | | { |
| | | printf("[%d] Send buffer data:\n", i); |
| | | cp_string_dump(snd); |
| | | } |
| | | } |
| | | |
| | | printf("\n=======================\n"); |
| | | printf("Test cp_string_move \n"); |
| | | printf("=======================\n"); |
| | | |
| | | cp_string_clear_data(snd); |
| | | cp_string_clear_data(rcv); |
| | | for(i=0; i<20; i++) |
| | | { |
| | | cp_string_cstrcpy(rcv, "Hello world!"); |
| | | //printf("Set new receive buffer data [%d] bytes:\n", cp_string_len(rcv)); |
| | | cp_string_dump(rcv); |
| | | |
| | | if( cp_string_move(snd, rcv) > 0) |
| | | { |
| | | printf("[%d] Send buffer [%d] bytes data:\n", i, cp_string_len(snd)); |
| | | cp_string_dump(snd); |
| | | |
| | | printf("[%d] receive buffer [%d] bytes data:\n", i, cp_string_len(rcv)); |
| | | cp_string_dump(rcv); |
| | | } |
| | | } |
| | | |
| | | cp_string_destroy(rcv); |
| | | cp_string_destroy(snd); |
| | | |
| | | |
| | | return 0; |
| | | } /* ----- End of main() ----- */ |
| | | |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: test_vector.c |
| | | * Description: This file used to test the vector library |
| | | * |
| | | * Version: 1.0.0(08/14/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "08/14/2012 05:17:03 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include <stdio.h> |
| | | #include <string.h> |
| | | #include <stdlib.h> |
| | | |
| | | #include "cp_vector.h" |
| | | #include "cp_sock.h" |
| | | |
| | | /******************************************************************************** |
| | | * Description: |
| | | * Input Args: |
| | | * Output Args: |
| | | * Return Value: |
| | | ********************************************************************************/ |
| | | int main (int argc, char **argv) |
| | | { |
| | | |
| | | int i, n; |
| | | CP_SOCK *p = NULL; |
| | | |
| | | CP_VECTOR *v = cp_vector_init(1024); |
| | | |
| | | for (i = 0; i < 10; i++) |
| | | { |
| | | p = cp_sock_init(NULL, 1024, 1024, 10, 30); |
| | | cp_vector_add(v, i, p); |
| | | } |
| | | |
| | | n = cp_vector_count(v); |
| | | for (i = 0; i < n; i++) |
| | | { |
| | | p = cp_vector_get(v, i); |
| | | printf("%d: %p\n", i, p); |
| | | } |
| | | |
| | | p = cp_sock_init(NULL, 1024, 1024, 10, 30); |
| | | cp_vector_add(v, 28, p); |
| | | printf("Set 28: %p\n", p); |
| | | |
| | | for (i=0; i <cp_vector_size(v); i++) |
| | | { |
| | | p = cp_vector_get(v, i); |
| | | if(p) |
| | | { |
| | | printf("Terminate socket %i: %p\n", i, p); |
| | | cp_sock_term(p); |
| | | } |
| | | } |
| | | |
| | | cp_vector_destroy(v); |
| | | |
| | | return 0; |
| | | |
| | | } /* ----- End of main() ----- */ |
| | | |
New file |
| | |
| | | [202-01] carrier='Cosmote Wireless Internet' apn='internet' uid='' pwd='' |
| | | [202-05] carrier='Vf Mobile Internet' apn='internet.vodafone.gr' uid='' pwd='' |
| | | [202-10] carrier='Wind Internet' apn='gint.b-online.gr' uid='' pwd='' |
| | | [204-04] carrier='Vodafone NL' apn='live.vodafone.com' uid='vodafone' pwd='vodafone' |
| | | [204-08] carrier='KPN Internet' apn='portalmmm.nl' uid='' pwd='' |
| | | [204-12] carrier='Telfort Internet' apn='internet' uid='' pwd='' |
| | | [204-16] carrier='T-Mobile Internet' apn='internet' uid='' pwd='' |
| | | [204-20] carrier='Rabo Mobiel' apn='rabo.plus' uid='' pwd='' |
| | | [206-01] carrier='Proximus Internet' apn='internet.proximus.be' uid='' pwd='' |
| | | [206-01] carrier='Telenet Internet' apn='telenetwap.be' uid='' pwd='' |
| | | [206-05] carrier='Telenet' apn='telenetwap.be' uid='' pwd='' |
| | | [206-10] carrier='Mobistar' apn='mworld.be' uid='mobistar' pwd='mobistar' |
| | | [206-20] carrier='Base' apn='gprs.base.be' uid='base' pwd='base' |
| | | [208-01] carrier='Orange World' apn='orange' uid='orange' pwd='orange' |
| | | [208-01] carrier='Orange Entreprise' apn='orange-mib' uid='orange' pwd='orange' |
| | | [208-01] carrier='Orange Internet' apn='orange.fr' uid='orange' pwd='orange' |
| | | [208-01] carrier='Orange Internet Entreprise' apn='internet-entreprise' uid='orange' pwd='orange' |
| | | [208-10] carrier='SFR webphone' apn='sl2sfr' uid='' pwd='' |
| | | [208-10] carrier='SFR Mobile' apn='wapsfr' uid='' pwd='' |
| | | [208-10] carrier='NRJWEB' apn='fnetnrj' uid='' pwd='' |
| | | [208-01] carrier='VM WAP' apn='ofnew.fr' uid='orange' pwd='orange' |
| | | [208-01] carrier='Tele2 WAP' apn='ofnew.fr' uid='orange' pwd='orange' |
| | | [208-01] carrier='Carrefour WAP' apn='ofnew.fr' uid='orange' pwd='orange' |
| | | [208-10] carrier='Auchan WAP' apn='wap65' uid='' pwd='' |
| | | [208-01] carrier='NRJWEB' apn='ofnew.fr' uid='orange' pwd='orange' |
| | | [208-10] carrier='WAP Simplicime' apn='wapdebitel' uid='' pwd='' |
| | | [208-10] carrier='WAP LeclercMobile' apn='wap66' uid='' pwd='' |
| | | [208-10] carrier='Coriolis WAP' apn='wapcoriolis' uid='' pwd='' |
| | | [208-10] carrier='Keyyo Mobile Internet' apn='internet68' uid='' pwd='' |
| | | [208-10] carrier='WEB La Poste Mobile' apn='wapdebitel' uid='' pwd='' |
| | | [214-01] carrier='Internet movil' apn='airtelwap.es' uid='wap@wap' pwd='wap125' |
| | | [214-03] carrier='Orange Internet Móvil' apn='orangeworld' uid='orange' pwd='orange' |
| | | [214-03] carrier='Orange Internet PC' apn='internet' uid='orange' pwd='orange' |
| | | [214-04] carrier='Yoigo Navegador' apn='internet' uid='' pwd='' |
| | | [214-06] carrier='INTERNET GPRS' apn='airtelnet.es' uid='vodafone' pwd='vodafone' |
| | | [214-06] carrier='Euskaltel Internet' apn='internet.euskaltel.mobi' uid='CLIENTE' pwd='EUSKALTEL' |
| | | [214-06] carrier='Internet R' apn='internet.mundo-r.com' uid='' pwd='' |
| | | [214-06] carrier='TeleCable Internet' apn='internet.telecable.es' uid='telecable' pwd='telecable' |
| | | [214-07] carrier='Movistar' apn='telefonica.es' uid='telefonica' pwd='telefonica' |
| | | [214-07] carrier='Conexión compartida' apn='movistar.es' uid='MOVISTAR' pwd='MOVISTAR' |
| | | [214-08] carrier='Euskaltel Internet' apn='internet.euskaltel.mobi' uid='CLIENTE' pwd='EUSKALTEL' |
| | | [214-16] carrier='TeleCable Internet' apn='internet.telecable.es' uid='telecable' pwd='telecable' |
| | | [216-01] carrier='Telenor Online' apn='online' uid='' pwd='' |
| | | [216-30] carrier='Web' apn='wnw' uid='' pwd='' |
| | | [216-70] carrier='VF internet' apn='internet.vodafone.net' uid='' pwd='' |
| | | [216-70] carrier='VMAX Internet' apn='vitamax.internet.vodafone.net' uid='' pwd='' |
| | | [218-03] carrier='HT Eronet' apn='wap.eronet.ba' uid='' pwd='' |
| | | [218-05] carrier='m:tel' apn='3g1' uid='' pwd='' |
| | | [218-90] carrier='Bh Mobile' apn='active.bhmobile.ba' uid='' pwd='' |
| | | [219-01] carrier='T-Mobile' apn='web.htgprs' uid='' pwd='' |
| | | [219-02] carrier='Tele2' apn='internet.tele2.hr' uid='' pwd='' |
| | | [219-10] carrier='Broadband' apn='data.vip.hr' uid='38591' pwd='38591' |
| | | [220-01] carrier='Telenor WAP' apn='internet' uid='telenor' pwd='gprs' |
| | | [220-02] carrier='Telenor MNE internet' apn='internet' uid='gprs' pwd='gprs' |
| | | [220-03] carrier='mt:s wap' apn='gprswap' uid='mts' pwd='64' |
| | | [220-04] carrier='T-Mobile Internet' apn='tmcg-wnw' uid='38267' pwd='38267' |
| | | [220-05] carrier='Vip GPRS' apn='vipmobile' uid='vipmobile' pwd='vipmobile' |
| | | [222-01] carrier='TIM WAP' apn='wap.tim.it' uid='WAPTIM' pwd='WAPTIM' |
| | | [222-01] carrier='TIM WEB' apn='ibox.tim.it' uid='' pwd='' |
| | | [222-10] carrier='Vodafone Internet' apn='mobile.vodafone.it' uid='' pwd='' |
| | | [222-10] carrier='Vodafone WEB' apn='web.omnitel.it' uid='' pwd='' |
| | | [222-88] carrier='WIND WEB' apn='internet.wind' uid='' pwd='' |
| | | [222-88] carrier='WIND BIZ WEB' apn='internet.wind.biz' uid='' pwd='' |
| | | [222-99] carrier='3' apn='tre.it' uid='' pwd='' |
| | | [222-99] carrier='Fastweb WEB' apn=' apn.fastweb.it' uid='' pwd='' |
| | | [226-01] carrier='Vodafone live!' apn='live.vodafone.com' uid='live' pwd='vodafone' |
| | | [226-01] carrier='Vodafone live! PRE' apn='live.pre.vodafone.com' uid='live' pwd='vodafone' |
| | | [226-03] carrier='Cosmote Internet' apn='internet' uid='' pwd='' |
| | | [226-03] carrier='web'n'walk' apn='wnw' uid='wnw' pwd='wnw' |
| | | [226-06] carrier='web'n'walk' apn='wnw' uid='wnw' pwd='wnw' |
| | | [226-10] carrier='Orange WAP' apn='wap' uid='' pwd='' |
| | | [226-10] carrier='Orange Internet' apn='net' uid='' pwd='' |
| | | [228-01] carrier='Swisscom Services' apn='gprs.swisscom.ch' uid='' pwd='' |
| | | [228-02] carrier='Sunrise live' apn='internet' uid='' pwd='' |
| | | [228-03] carrier='Orange Internet' apn='internet' uid='' pwd='' |
| | | [230-01] carrier='T-Mobile CZ' apn='internet.t-mobile.cz' uid='wap' pwd='wap' |
| | | [230-02] carrier='O2 internet' apn='internet' uid='' pwd='' |
| | | [230-03] carrier='GPRS Web' apn='internet' uid='' pwd='' |
| | | [231-01] carrier='Orange SK' apn='internet' uid='' pwd='' |
| | | [231-01] carrier='Orange World' apn='orangewap' uid='wap' pwd='wap' |
| | | [231-02] carrier='T-Mobile internet' apn='internet' uid='' pwd='' |
| | | [231-06] carrier='O2 internet' apn='o2internet' uid='' pwd='' |
| | | [232-01] carrier='A1' apn='a1.net' uid='ppp@a1plus.at' pwd='ppp' |
| | | [232-01] carrier='aonMobil' apn='aon.at' uid='mobil@aon.at' pwd='ppp' |
| | | [232-03] carrier='T-Mobile Internet' apn='gprsinternet' uid='t-mobile' pwd='tm' |
| | | [232-05] carrier='Orange Smartphone' apn='orange.smartphone' uid='web' pwd='web' |
| | | [232-07] carrier='tele.ring web' apn='web' uid='web@telering.at' pwd='web' |
| | | [232-10] carrier='Planet3' apn='drei.at' uid='' pwd='' |
| | | [232-11] carrier='data.bob' apn='bob.at' uid='data@bob.at' pwd='ppp' |
| | | [232-12] carrier='YESSS! GPRS' apn='web.yesss.at' uid='' pwd='' |
| | | [234-01] carrier='UBIQUISYS' apn='internet' uid='' pwd='' |
| | | [234-02] carrier='O2 MOBILE WEB' apn='mobile.o2.co.uk' uid='O2web' pwd='O2web' |
| | | [234-10] carrier='O2 Mobile Web' apn='mobile.o2.co.uk' uid='o2web' pwd='password' |
| | | [234-10] carrier='O2 PREPAY' apn='payandgo.o2.co.uk' uid='payandgo' pwd='password' |
| | | [234-10] carrier='TESCO' apn='prepay.tesco-mobile.com' uid='tescowap' pwd='password' |
| | | [234-11] carrier='O2 MOBILE WEB' apn='mobile.o2.co.uk' uid='O2web' pwd='O2web' |
| | | [234-11] carrier='O2 MOBILE WEB' apn='mobile.o2.co.uk' uid='O2web' pwd='O2web' |
| | | [234-15] carrier='Vodafone UK' apn='wap.vodafone.co.uk' uid='wap' pwd='wap' |
| | | [234-15] carrier='Vodafone UK Prepay' apn='pp.vodafone.co.uk' uid='wap' pwd='wap' |
| | | [234-20] carrier='3' apn='three.co.uk' uid='' pwd='' |
| | | [234-30] carrier='T-Mobile UK' apn='general.t-mobile.uk' uid='t-mobile' pwd='tm' |
| | | [234-30] carrier='Virgin Media' apn='goto.virginmobile.uk' uid='user' pwd='' |
| | | [234-31] carrier='T-Mobile Internet' apn='general.t-mobile.uk' uid='t-mobile' pwd='tm' |
| | | [234-31] carrier='T-Mobile Picture Message' apn='general.t-mobile.uk' uid='t-mobile' pwd='tm' |
| | | [234-32] carrier='T-Mobile Internet' apn='general.t-mobile.uk' uid='t-mobile' pwd='tm' |
| | | [234-32] carrier='T-Mobile Picture Message' apn='general.t-mobile.uk' uid='t-mobile' pwd='tm' |
| | | [234-33] carrier='Orange Internet' apn='orangeinternet' uid='' pwd='' |
| | | [234-33] carrier='Consumer Broadband' apn='consumerbroadband' uid='' pwd='' |
| | | [234-34] carrier='Orange internet' apn='orangeinternet' uid='' pwd='' |
| | | [234-50] carrier='pepperWEB (Jersey)' apn='pepper' uid='' pwd='' |
| | | [234-55] carrier='C&W Guernsey Internet' apn='internet' uid='' pwd='' |
| | | [234-58] carrier='3G HSDPA' apn='3gpronto' uid='' pwd='' |
| | | [234-58] carrier='Manx Telecom Contract WEB' apn='web.manxpronto.net' uid='gprs' pwd='gprs' |
| | | [234-86] carrier='Orange internet' apn='orangeinternet' uid='' pwd='' |
| | | [238-01] carrier='TDC' apn='internet' uid='' pwd='' |
| | | [238-01] carrier='TDC Song WAP' apn='internet.no' uid='' pwd='' |
| | | [238-01] carrier='TDC WAP' apn='wap' uid='' pwd='' |
| | | [238-01] carrier='Telmore Wap' apn='wap' uid='' pwd='' |
| | | [238-02] carrier='Telenor Internet' apn='Internet' uid='' pwd='' |
| | | [238-06] carrier='3' apn='data.tre.dk' uid='' pwd='' |
| | | [238-20] carrier='Internet' apn='websp' uid='' pwd='' |
| | | [238-20] carrier='Telia Internet' apn='www.internet.mtelia.dk' uid='' pwd='' |
| | | [238-77] carrier='Telenor Internet' apn='Internet' uid='' pwd='' |
| | | [240-01] carrier='Telia SE WAP' apn='online.telia.se' uid='' pwd='' |
| | | [240-17] carrier='Halebop Internet' apn='halebop.telia.se' uid='' pwd='' |
| | | [240-02] carrier='3' apn='data.tre.se' uid='' pwd='' |
| | | [240-04] carrier='Telenor Mobilsurf' apn='services.telenor.se' uid='' pwd='' |
| | | [240-06] carrier='Telenor Mobilsurf' apn='services.telenor.se' uid='' pwd='' |
| | | [240-07] carrier='Tele2' apn='internet.tele2.no' uid='' pwd='' |
| | | [240-07] carrier='Tele2' apn='internet.tele2.se' uid='' pwd='' |
| | | [240-08] carrier='Telenor Mobilsurf' apn='services.telenor.se' uid='' pwd='' |
| | | [240-09] carrier='TelenorMobilsurf' apn='services.telenor.se' uid='' pwd='' |
| | | [240-10] carrier='Spring data' apn='data.springmobil.se' uid='' pwd='' |
| | | [242-01] carrier='Ventelo Internett' apn='internet.ventelo.no' uid='' pwd='' |
| | | [242-01] carrier='Telenor' apn='telenor' uid='' pwd='' |
| | | [242-02] carrier='NetCom Internett' apn='wap' uid='' pwd='' |
| | | [242-04] carrier='Tele2 Internett' apn='internet.tele2.no' uid='' pwd='' |
| | | [242-05] carrier='NwN Internet' apn='internet' uid='' pwd='' |
| | | [244-03] carrier='DNA Internet' apn='internet' uid='' pwd='' |
| | | [244-04] carrier='DNA Internet' apn='internet' uid='' pwd='' |
| | | [244-05] carrier='Elisa Internet' apn='internet' uid='' pwd='' |
| | | [244-10] carrier='TDC Internet' apn='internet.song.fi' uid='song@internet' pwd='songnet' |
| | | [244-12] carrier='DNA Pro Internet' apn='dnapro.fi' uid='' pwd='' |
| | | [244-12] carrier='TDC Internet Finland' apn='inet.tdc.fi' uid='' pwd='' |
| | | [244-13] carrier='DNA Internet' apn='internet' uid='' pwd='' |
| | | [244-21] carrier='Saunalahti Internet' apn='internet.saunalahti' uid='' pwd='' |
| | | [244-91] carrier='SONERA Internet' apn='internet' uid='' pwd='' |
| | | [246-01] carrier='Omnitel Internet' apn='omnitel' uid='omni' pwd='omni' |
| | | [246-02] carrier='Bite LT WAP' apn='wap' uid='' pwd='' |
| | | [246-03] carrier='Tele2 Internet LT' apn='internet.tele2.lt' uid='wap' pwd='wap' |
| | | [247-01] carrier='LMT Internet' apn='internet.lmt.lv' uid='' pwd='' |
| | | [247-02] carrier='Tele2 LV Internet' apn='internet.tele2.lv' uid='wap' pwd='wap' |
| | | [247-05] carrier='Bite LV Internet' apn='internet' uid='' pwd='' |
| | | [247-05] carrier='Bite LV WAP' apn='wap' uid='' pwd='' |
| | | [248-01] carrier='EMT Internet' apn='internet.emt.ee' uid='' pwd='' |
| | | [248-01] carrier='EMT WAP' apn='wap.emt.ee' uid='' pwd='' |
| | | [248-02] carrier='Elisa Internet' apn='internet' uid='' pwd='' |
| | | [248-02] carrier='Elisa WAP' apn='wap' uid='' pwd='' |
| | | [248-03] carrier='Tele2 Internet' apn='internet.tele2.ee' uid='' pwd='' |
| | | [250-01] carrier='MTS Internet' apn='internet.mts.ru' uid='mts' pwd='mts' |
| | | [250-02] carrier='Megafon Internet' apn='internet' uid='gdata' pwd='gdata' |
| | | [250-99] carrier='Beeline Internet' apn='internet.beeline.ru' uid='beeline' pwd='beeline' |
| | | [250-20] carrier='TELE2 Internet' apn='internet.tele2.ru' uid='' pwd='' |
| | | [255-01] carrier='MTS-internet' apn='internet' uid='' pwd='' |
| | | [255-02] carrier='Beeline-internet' apn='internet.beeline.ua' uid='' pwd='' |
| | | [255-03] carrier='Kyivstar Internet' apn='www.kyivstar.net' uid='' pwd='' |
| | | [255-06] carrier='life:) internet' apn='internet' uid='' pwd='' |
| | | [255-07] carrier='Utel Internet' apn='3g.utel.ua' uid='' pwd='' |
| | | [260-01] carrier='Plus Internet' apn='internet' uid='' pwd='' |
| | | [260-02] carrier='T-mobile.pl' apn='internet' uid='' pwd='' |
| | | [260-02] carrier='heyahinternet' apn='heyah.pl' uid='' pwd='' |
| | | [260-03] carrier='Internet' apn='Internet' uid='internet' pwd='internet' |
| | | [260-06] carrier='P4 Internet' apn='internet' uid='' pwd='' |
| | | [262-01] carrier='T-Mobile Internet' apn='internet.t-mobile' uid='t-mobile' pwd='tm' |
| | | [262-02] carrier='Vodafone DE' apn='web.vodafone.de' uid='' pwd='' |
| | | [262-03] carrier='E-Plus Web GPRS' apn='internet.eplus.de' uid='eplus' pwd='internet' |
| | | [262-07] carrier='o2' apn='internet' uid='' pwd='' |
| | | [262-07] carrier='o2 Internet Prepaid' apn='pinternet.interkom.de' uid='' pwd='' |
| | | [268-01] carrier='Vodafone Net2' apn='net2.vodafone.pt' uid='vodafone' pwd='vodafone' |
| | | [268-03] carrier='Optimus Internet' apn='umts' uid='' pwd='' |
| | | [268-06] carrier='tmn internet' apn='internet' uid='' pwd='' |
| | | [270-01] carrier='LUXGSM WAP' apn='wap.pt.lu' uid='wap' pwd='wap' |
| | | [270-77] carrier='Tango WAP' apn='internet' uid='tango' pwd='tango' |
| | | [270-99] carrier='Vox Mobile' apn='vox.lu' uid='' pwd='' |
| | | [272-01] carrier='Vodafone IE' apn='live.vodafone.com' uid='' pwd='' |
| | | [272-02] carrier='O2 Ireland' apn='internet' uid='' pwd='' |
| | | [272-03] carrier='Meteor Data' apn='data.mymeteor.ie' uid='' pwd='' |
| | | [272-05] carrier='3' apn='3ireland.ie' uid='' pwd='' |
| | | [272-11] carrier='Tesco' apn='tescomobile.liffeytelecom.com' uid='' pwd='' |
| | | [274-01] carrier='Siminn Internet' apn='internet' uid='' pwd='' |
| | | [274-02] carrier='Vodafone Internet' apn='gprs.is' uid='' pwd='' |
| | | [274-11] carrier='Net Nova' apn='net.nova.is' uid='' pwd='' |
| | | [278-01] carrier='Vodafone MT' apn='internet' uid='internet' pwd='internet' |
| | | [280-01] carrier='CYTA' apn='cytamobile' uid='user' pwd='pass' |
| | | [280-10] carrier='MTN Wap' apn='wap' uid='wap' pwd='wap' |
| | | [284-01] carrier='M-Tel' apn='wap-gprs.mtel.bg' uid='' pwd='' |
| | | [284-03] carrier='Vivacom WAP' apn='wap.vivacom.bg' uid='wap' pwd='wap' |
| | | [284-05] carrier='GPRS GLOBUL' apn='globul' uid='' pwd='' |
| | | [286-01] carrier='Turkcell Internet' apn='internet' uid='gprs' pwd='gprs' |
| | | [286-02] carrier='Vodafone Internet' apn='internet' uid='vodafone' pwd='vodafone' |
| | | [286-03] carrier='Avea Internet' apn='internet' uid='wap' pwd='wap' |
| | | [290-01] carrier='Tele Internet' apn='internet' uid='' pwd='' |
| | | [293-40] carrier='Vodafone live!' apn='internet.simobil.si' uid='simobil' pwd='internet' |
| | | [293-41] carrier='Planet' apn='internet' uid='mobitel' pwd='internet' |
| | | [294-01] carrier='T-Mobile MK Internet' apn='internet' uid='internet' pwd='t-mobile' |
| | | [294-02] carrier='Cosmofon' apn='Internet' uid='Internet' pwd='Internet' |
| | | [294-03] carrier='Internet' apn='vipoperator' uid='vipoperator' pwd='vipoperator' |
| | | [297-02] carrier='T-Mobile Internet' apn='tmcg-wnw' uid='38267' pwd='38267' |
| | | [302-220] carrier='TELUS' apn='sp.telus.com' uid='' pwd='' |
| | | [302-320] carrier='MOWAP' apn='wap.davewireless.com' uid='' pwd='' |
| | | [302-370] carrier='Fido Internet' apn='fido-core-appl1.apn' uid='' pwd='' |
| | | [302-370] carrier='Fido Tethering' apn='isp.fido.apn' uid='' pwd='' |
| | | [302-720] carrier='Chatr Internet' apn='chatrweb.apn' uid='' pwd='' |
| | | [302-490] carrier='Wind CA' apn='internet.windmobile.ca' uid='' pwd='' |
| | | [302-500] carrier='Videotron' apn='media.videotron' uid='' pwd='' |
| | | [302-610] carrier='Bell Internet' apn='pda.bell.ca' uid='' pwd='' |
| | | [302-720] carrier='Rogers Tethering' apn='isp.apn' uid='' pwd='' |
| | | [302-720] carrier='Rogers' apn='rogers-core-appl1.apn' uid='' pwd='' |
| | | [302-780] carrier='SaskTel' apn='pda.stm.sk.ca' uid='' pwd='' |
| | | [310-30] carrier='Internet' apn='private.centennialwireless.com' uid='privuser' pwd='priv' |
| | | [310-90] carrier='Internet' apn='isp' uid='' pwd='' |
| | | [310-100] carrier='PLATWEB' apn='plateauweb' uid='' pwd='' |
| | | [310-160] carrier='T-Mobile US 160' apn='epc.tmobile.com' uid='' pwd='' |
| | | [310-170] carrier='DataConnect' apn='isp.cingular' uid='' pwd='' |
| | | [310-200] carrier='T-Mobile US 200' apn='epc.tmobile.com' uid='' pwd='' |
| | | [310-210] carrier='T-Mobile US 210' apn='epc.tmobile.com' uid='' pwd='' |
| | | [310-220] carrier='T-Mobile US 220' apn='epc.tmobile.com' uid='' pwd='' |
| | | [310-230] carrier='T-Mobile US 230' apn='epc.tmobile.com' uid='' pwd='' |
| | | [310-240] carrier='T-Mobile US 240' apn='epc.tmobile.com' uid='' pwd='' |
| | | [310-250] carrier='T-Mobile US 250' apn='epc.tmobile.com' uid='' pwd='' |
| | | [310-260] carrier='T-Mobile US' apn='epc.tmobile.com' uid='' pwd='' |
| | | [310-270] carrier='T-Mobile US 270' apn='epc.tmobile.com' uid='' pwd='' |
| | | [310-310] carrier='T-Mobile US 310' apn='epc.tmobile.com' uid='' pwd='' |
| | | [310-380] carrier='Cingular 380 ATT' apn='proxy' uid='' pwd='' |
| | | [310-410] carrier='Cingular 410' apn='wap.cingular' uid='WAP@CINGULARGPRS.COM' pwd='CINGULAR1' |
| | | [310-470] carrier='DataConnect' apn='isp.cingular' uid='' pwd='' |
| | | [310-470] carrier='MediaNet' apn='wap.cingular' uid='WAP@CINGULARGPRS.COM' pwd='CINGULAR1' |
| | | [310-480] carrier='DataConnect' apn='isp.cingular' uid='' pwd='' |
| | | [310-480] carrier='MediaNet' apn='wap.cingular' uid='WAP@CINGULARGPRS.COM' pwd='CINGULAR1' |
| | | [310-490] carrier='T-Mobile US 490' apn='epc.tmobile.com' uid='' pwd='' |
| | | [310-490] carrier='GoodCall Picture Message' apn='good.call' uid='' pwd='' |
| | | [310-580] carrier='T-Mobile US 580' apn='epc.tmobile.com' uid='' pwd='' |
| | | [310-610] carrier='EpicINT' apn='internet.epictouch' uid='' pwd='' |
| | | [310-660] carrier='T-Mobile US 660' apn='epc.tmobile.com' uid='' pwd='' |
| | | [310-770] carrier='WEB 2' apn='i2.iwireless.com' uid='' pwd='' |
| | | [310-770] carrier='Picture Messaging' apn='wap1.iwireless.com' uid='' pwd='' |
| | | [310-770] carrier='PIAPicture Messaging' apn='wap9.iwireless.com' uid='' pwd='' |
| | | [310-800] carrier='T-Mobile US 800' apn='epc.tmobile.com' uid='' pwd='' |
| | | [310-840] carrier='Internet' apn='isp' uid='' pwd='' |
| | | [310-910] carrier='WOW_WAP' apn='wap.firstcellular.com' uid='' pwd='' |
| | | [311-210] carrier='Farmers GPRS' apn='internet.farmerswireless.com' uid='' pwd='' |
| | | [330-110] carrier='INTERNET CLARO' apn='internet.claropr.com' uid='' pwd='' |
| | | [334-20] carrier='Internet' apn='internet.itelcel.com' uid='webgprs' pwd='webgprs2002' |
| | | [334-03] carrier='movistar Internet' apn='internet.movistar.mx' uid='movistar' pwd='movistar' |
| | | [334-30] carrier='movistar Internet' apn='internet.movistar.mx' uid='movistar' pwd='movistar' |
| | | [334-50] carrier='Iusacell Internet' apn='web.iusacellgsm.mx' uid='Iusacellgsm' pwd='Iusacellgsm' |
| | | [338-50] carrier='INTERNET Digicel' apn='web.digiceljamaica.com' uid='' pwd='' |
| | | [338-18] carrier='Lime Internet Postpaid' apn='internet' uid='' pwd='' |
| | | [338-70] carrier='Claro Web' apn='internet.ideasclaro.com.jm' uid='' pwd='' |
| | | [338-180] carrier='Lime Internet Postpaid' apn='internet' uid='' pwd='' |
| | | [340-01] carrier='Orange World Caraïbe' apn='orangewap' uid='orange' pwd='wap' |
| | | [340-20] carrier='Digicel FR' apn='wap.digicelfr.com' uid='wap' pwd='wap' |
| | | [342-60] carrier='Lime Internet Postpaid' apn='internet' uid='' pwd='' |
| | | [344-92] carrier='Lime Internet Postpaid' apn='internet' uid='' pwd='' |
| | | [346-14] carrier='Lime Internet Postpaid' apn='internet' uid='' pwd='' |
| | | [348-17] carrier='Lime Internet Postpaid' apn='internet' uid='' pwd='' |
| | | [352-11] carrier='Lime Internet Postpaid' apn='internet' uid='' pwd='' |
| | | [354-86] carrier='Lime Internet Postpaid' apn='internet' uid='' pwd='' |
| | | [356-11] carrier='Lime Internet Postpaid' apn='internet' uid='' pwd='' |
| | | [358-11] carrier='Lime Internet Postpaid' apn='internet' uid='' pwd='' |
| | | [360-11] carrier='Lime Internet Postpaid' apn='internet' uid='' pwd='' |
| | | [363-02] carrier='INTERNET Aruba' apn='web.digicelaruba.com' uid='' pwd='' |
| | | [363-20] carrier='INTERNET Aruba' apn='web.digicelaruba.com' uid='' pwd='' |
| | | [365-84] carrier='Lime Internet Postpaid' apn='internet' uid='' pwd='' |
| | | [366-11] carrier='Lime Internet Postpaid' apn='internet' uid='' pwd='' |
| | | [368-01] carrier='Internet' apn='internet' uid='' pwd='' |
| | | [370-01] carrier='Orange net' apn='orangenet.com.do' uid='' pwd='' |
| | | [370-02] carrier='INTERNET CLARO' apn='internet.ideasclaro.com.do' uid='' pwd='' |
| | | [370-04] carrier='Viva Edge' apn='edge.viva.net.do' uid='viva' pwd='viva' |
| | | [374-12] carrier='Bmobile internet' apn='internet' uid='' pwd='' |
| | | [374-120] carrier='Bmobile internet' apn='internet' uid='' pwd='' |
| | | [374-121] carrier='Bmobile internet' apn='internet' uid='' pwd='' |
| | | [374-122] carrier='Bmobile internet' apn='internet' uid='' pwd='' |
| | | [374-123] carrier='Bmobile internet' apn='internet' uid='' pwd='' |
| | | [374-124] carrier='Bmobile internet' apn='internet' uid='' pwd='' |
| | | [374-125] carrier='Bmobile internet' apn='internet' uid='' pwd='' |
| | | [374-126] carrier='Bmobile internet' apn='internet' uid='' pwd='' |
| | | [374-127] carrier='Bmobile internet' apn='internet' uid='' pwd='' |
| | | [374-128] carrier='Bmobile internet' apn='internet' uid='' pwd='' |
| | | [374-129] carrier='Bmobile internet' apn='internet' uid='' pwd='' |
| | | [374-13] carrier='INTERNET Trinidad' apn='web.digiceltt.com' uid='' pwd='' |
| | | [374-130] carrier='INTERNET Trinidad' apn='web.digiceltt.com' uid='' pwd='' |
| | | [376-35] carrier='Lime Internet Postpaid' apn='internet' uid='' pwd='' |
| | | [401-01] carrier='Beeline Internet' apn='internet.beeline.kz' uid='@internet.beeline' pwd='beeline' |
| | | [401-02] carrier='Kcell Internet' apn='internet' uid='' pwd='' |
| | | [401-77] carrier='Tele2 Internet' apn='internet' uid='' pwd='' |
| | | [404-01] carrier='Vodafone Connect' apn='www' uid='' pwd='' |
| | | [404-02] carrier='Airtel' apn='airtelgprs.com' uid='' pwd='' |
| | | [404-03] carrier='Airtel' apn='airtelgprs.com' uid='' pwd='' |
| | | [404-04] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [404-05] carrier='Vodafone Connect' apn='www' uid='' pwd='' |
| | | [404-07] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [404-09] carrier='Reliance RTel' apn='SMARTNET' uid='' pwd='' |
| | | [404-10] carrier='Airtel' apn='airtelgprs.com' uid='' pwd='' |
| | | [404-11] carrier='Vodafone Connect' apn='www' uid='' pwd='' |
| | | [404-12] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [404-13] carrier='Vodafone Connect' apn='www' uid='' pwd='' |
| | | [404-14] carrier='IDEA Punjab' apn='spicegprs' uid='' pwd='' |
| | | [404-15] carrier='Vodafone Connect' apn='www' uid='' pwd='' |
| | | [404-16] carrier='Airtel' apn='airtelgprs.com' uid='' pwd='' |
| | | [404-17] carrier='AIRCEL NE' apn='aircelwebpost' uid='' pwd='' |
| | | [404-18] carrier='Reliance RTel' apn='SMARTNET' uid='' pwd='' |
| | | [404-19] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [404-20] carrier='Vodafone Connect' apn='www' uid='' pwd='' |
| | | [404-21] carrier='Loop Mobile' apn='www' uid='' pwd='' |
| | | [404-22] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [404-24] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [404-25] carrier='AIRCEL NE' apn='aircelwebpost' uid='' pwd='' |
| | | [404-27] carrier='Vodafone Connect' apn='www' uid='' pwd='' |
| | | [404-28] carrier='AIRCEL NE' apn='aircelwebpost' uid='' pwd='' |
| | | [404-29] carrier='AIRCEL NE' apn='aircelwebpost' uid='' pwd='' |
| | | [404-30] carrier='Vodafone Connect' apn='www' uid='' pwd='' |
| | | [404-31] carrier='Airtel' apn='airtelgprs.com' uid='' pwd='' |
| | | [404-33] carrier='AIRCEL NE' apn='aircelwebpost' uid='' pwd='' |
| | | [404-34] carrier='Cellone_North' apn='bsnlnet' uid='' pwd='' |
| | | [404-35] carrier='AIRCEL NE' apn='aircelwebpost' uid='' pwd='' |
| | | [404-36] carrier='Reliance RTel' apn='SMARTNET' uid='' pwd='' |
| | | [404-37] carrier='AIRCEL NE' apn='aircelwebpost' uid='' pwd='' |
| | | [404-38] carrier='CellOne_Kolkata' apn='bsnlnet' uid='' pwd='' |
| | | [404-40] carrier='Airtel' apn='airtelgprs.com' uid='' pwd='' |
| | | [404-41] carrier='AIRCEL TN' apn='aircelgprs.po' uid='' pwd='' |
| | | [404-42] carrier='AIRCEL TN' apn='aircelgprs.po' uid='' pwd='' |
| | | [404-43] carrier='Vodafone Connect' apn='www' uid='' pwd='' |
| | | [404-44] carrier='IDEA Karnataka' apn='simplyinternet' uid='' pwd='' |
| | | [404-45] carrier='Airtel' apn='airtelgprs.com' uid='' pwd='' |
| | | [404-46] carrier='Vodafone Connect' apn='www' uid='' pwd='' |
| | | [404-49] carrier='Airtel' apn='airtelgprs.com' uid='' pwd='' |
| | | [404-50] carrier='Reliance RTel' apn='SMARTNET' uid='' pwd='' |
| | | [404-51] carrier='Cellone_North' apn='bsnlnet' uid='' pwd='' |
| | | [404-52] carrier='Reliance RTel' apn='SMARTNET' uid='' pwd='' |
| | | [404-53] carrier='Cellone_North' apn='bsnlnet' uid='' pwd='' |
| | | [404-54] carrier='Cellone_North' apn='bsnlnet' uid='' pwd='' |
| | | [404-55] carrier='Cellone_North' apn='bsnlnet' uid='' pwd='' |
| | | [404-56] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [404-57] carrier='Cellone_West' apn='bsnlnet' uid='' pwd='' |
| | | [404-58] carrier='Cellone_West' apn='bsnlnet' uid='' pwd='' |
| | | [404-59] carrier='Cellone_North' apn='bsnlnet' uid='' pwd='' |
| | | [404-60] carrier='Vodafone Connect' apn='www' uid='' pwd='' |
| | | [404-62] carrier='Cellone_North' apn='bsnlnet' uid='' pwd='' |
| | | [404-64] carrier='CellOne_South' apn='bsnlnet' uid='' pwd='' |
| | | [404-66] carrier='Cellone_West' apn='bsnlnet' uid='' pwd='' |
| | | [404-67] carrier='Reliance RTel' apn='SMARTNET' uid='' pwd='' |
| | | [404-68] carrier='Dolphin_Delhi' apn='gprsmtnldel' uid='mtnl' pwd='mtnl123' |
| | | [404-68] carrier='Dolphin_Delhi_3G' apn='mtnl3g' uid='mtnl' pwd='mtnl123' |
| | | [404-69] carrier='Dolphin_Mumbai' apn='gprsmtnlmum' uid='mtnl' pwd='mtnl123' |
| | | [404-69] carrier='Dolphin_Mumbai_3G' apn='mtnl3g' uid='mtnl' pwd='mtnl123' |
| | | [404-70] carrier='Airtel' apn='airtelgprs.com' uid='' pwd='' |
| | | [404-71] carrier='CellOne_South' apn='bsnlnet' uid='' pwd='' |
| | | [404-72] carrier='CellOne_South' apn='bsnlnet' uid='' pwd='' |
| | | [404-73] carrier='CellOne_South' apn='bsnlnet' uid='' pwd='' |
| | | [404-74] carrier='CellOne_Kolkata' apn='bsnlnet' uid='' pwd='' |
| | | [404-75] carrier='CellOne_Kolkata' apn='bsnlnet' uid='' pwd='' |
| | | [404-76] carrier='CellOne_Kolkata' apn='bsnlnet' uid='' pwd='' |
| | | [404-77] carrier='CellOne_Kolkata' apn='bsnlnet' uid='' pwd='' |
| | | [404-78] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [404-79] carrier='CellOne_South' apn='bsnlnet' uid='' pwd='' |
| | | [404-80] carrier='CellOne_South' apn='bsnlnet' uid='' pwd='' |
| | | [404-81] carrier='CellOne_Kolkata' apn='bsnlnet' uid='' pwd='' |
| | | [404-82] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [404-83] carrier='Reliance RTel' apn='SMARTNET' uid='' pwd='' |
| | | [404-84] carrier='Vodafone Connect' apn='www' uid='' pwd='' |
| | | [404-85] carrier='Reliance RTel' apn='SMARTNET' uid='' pwd='' |
| | | [404-86] carrier='Vodafone Connect' apn='www' uid='' pwd='' |
| | | [404-87] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [404-88] carrier='Vodafone Connect' apn='www' uid='' pwd='' |
| | | [404-89] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [404-90] carrier='Airtel' apn='airtelgprs.com' uid='' pwd='' |
| | | [404-91] carrier='AIRCEL NE' apn='aircelwebpost' uid='' pwd='' |
| | | [404-92] carrier='Airtel' apn='airtelgprs.com' uid='' pwd='' |
| | | [404-93] carrier='Airtel' apn='airtelgprs.com' uid='' pwd='' |
| | | [404-94] carrier='Airtel' apn='airtelgprs.com' uid='' pwd='' |
| | | [404-95] carrier='Airtel' apn='airtelgprs.com' uid='' pwd='' |
| | | [404-96] carrier='Airtel' apn='airtelgprs.com' uid='' pwd='' |
| | | [404-97] carrier='Airtel' apn='airtelgprs.com' uid='' pwd='' |
| | | [404-98] carrier='Airtel' apn='airtelgprs.com' uid='' pwd='' |
| | | [405-01] carrier='Reliance RCOM' apn='rcomnet' uid='' pwd='' |
| | | [405-03] carrier='Reliance RCOM' apn='rcomnet' uid='' pwd='' |
| | | [405-04] carrier='Reliance RCOM' apn='rcomnet' uid='' pwd='' |
| | | [405-05] carrier='Reliance RCOM' apn='rcomnet' uid='' pwd='' |
| | | [405-06] carrier='Reliance RCOM' apn='rcomnet' uid='' pwd='' |
| | | [405-07] carrier='Reliance RCOM' apn='rcomnet' uid='' pwd='' |
| | | [405-08] carrier='Reliance RCOM' apn='rcomnet' uid='' pwd='' |
| | | [405-09] carrier='Reliance RCOM' apn='rcomnet' uid='' pwd='' |
| | | [405-10] carrier='Reliance RCOM' apn='rcomnet' uid='' pwd='' |
| | | [405-11] carrier='Reliance RCOM' apn='rcomnet' uid='' pwd='' |
| | | [405-12] carrier='Reliance RCOM' apn='rcomnet' uid='' pwd='' |
| | | [405-13] carrier='Reliance RCOM' apn='rcomnet' uid='' pwd='' |
| | | [405-14] carrier='Reliance RCOM' apn='rcomnet' uid='' pwd='' |
| | | [405-15] carrier='Reliance RCOM' apn='rcomnet' uid='' pwd='' |
| | | [405-17] carrier='Reliance RCOM' apn='rcomnet' uid='' pwd='' |
| | | [405-18] carrier='Reliance RCOM' apn='rcomnet' uid='' pwd='' |
| | | [405-19] carrier='Reliance RCOM' apn='rcomnet' uid='' pwd='' |
| | | [405-20] carrier='Reliance RCOM' apn='rcomnet' uid='' pwd='' |
| | | [405-21] carrier='Reliance RCOM' apn='rcomnet' uid='' pwd='' |
| | | [405-22] carrier='Reliance RCOM' apn='rcomnet' uid='' pwd='' |
| | | [405-23] carrier='Reliance RCOM' apn='rcomnet' uid='' pwd='' |
| | | [405-25] carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd='' |
| | | [405-26] carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd='' |
| | | [405-27] carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd='' |
| | | [405-28] carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd='' |
| | | [405-29] carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd='' |
| | | [405-30] carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd='' |
| | | [405-31] carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd='' |
| | | [405-32] carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd='' |
| | | [405-33] carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd='' |
| | | [405-34] carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd='' |
| | | [405-35] carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd='' |
| | | [405-36] carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd='' |
| | | [405-37] carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd='' |
| | | [405-38] carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd='' |
| | | [405-39] carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd='' |
| | | [405-40] carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd='' |
| | | [405-41] carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd='' |
| | | [405-42] carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd='' |
| | | [405-43] carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd='' |
| | | [405-44] carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd='' |
| | | [405-45] carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd='' |
| | | [405-46] carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd='' |
| | | [405-47] carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd='' |
| | | [405-51] carrier='Airtel' apn='airtelgprs.com' uid='' pwd='' |
| | | [405-52] carrier='Airtel' apn='airtelgprs.com' uid='' pwd='' |
| | | [405-53] carrier='Airtel' apn='airtelgprs.com' uid='' pwd='' |
| | | [405-54] carrier='Airtel' apn='airtelgprs.com' uid='' pwd='' |
| | | [405-55] carrier='Airtel' apn='airtelgprs.com' uid='' pwd='' |
| | | [405-56] carrier='Airtel' apn='airtelgprs.com' uid='' pwd='' |
| | | [405-66] carrier='Vodafone Connect' apn='www' uid='' pwd='' |
| | | [405-67] carrier='Vodafone Connect' apn='www' uid='' pwd='' |
| | | [405-70] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [405-750] carrier='Vodafone Connect' apn='jkgprs' uid='' pwd='' |
| | | [405-750] carrier='VodafoneLive!' apn='vodafonelivejk' uid='' pwd='' |
| | | [405-751] carrier='Vodafone Connect' apn='www' uid='' pwd='' |
| | | [405-752] carrier='Vodafone Connect' apn='www' uid='' pwd='' |
| | | [405-753] carrier='Vodafone Connect' apn='www' uid='' pwd='' |
| | | [405-754] carrier='Vodafone Connect' apn='www' uid='' pwd='' |
| | | [405-755] carrier='Vodafone Connect' apn='www' uid='' pwd='' |
| | | [405-756] carrier='Vodafone Connect' apn='www' uid='' pwd='' |
| | | [405-799] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [405-800] carrier='AIRCEL ROI' apn='aircelgprs' uid='' pwd='' |
| | | [405-801] carrier='AIRCEL South' apn='aircelgprs' uid='' pwd='' |
| | | [405-802] carrier='AIRCEL Central' apn='aircelgprs' uid='' pwd='' |
| | | [405-803] carrier='AIRCEL South' apn='aircelgprs' uid='' pwd='' |
| | | [405-804] carrier='AIRCEL ROI' apn='aircelgprs' uid='' pwd='' |
| | | [405-805] carrier='AIRCEL ROI' apn='aircelgprs' uid='' pwd='' |
| | | [405-806] carrier='AIRCEL Central' apn='aircelgprs' uid='' pwd='' |
| | | [405-807] carrier='AIRCEL Central' apn='aircelgprs' uid='' pwd='' |
| | | [405-808] carrier='AIRCEL Central' apn='aircelgprs' uid='' pwd='' |
| | | [405-809] carrier='AIRCEL South' apn='aircelgprs' uid='' pwd='' |
| | | [405-810] carrier='AIRCEL ROI' apn='aircelgprs' uid='' pwd='' |
| | | [405-811] carrier='AIRCEL ROI' apn='aircelgprs' uid='' pwd='' |
| | | [405-812] carrier='AIRCEL Central' apn='aircelgprs' uid='' pwd='' |
| | | [405-813] carrier='Uninor GPRS' apn='uninor' uid='' pwd='' |
| | | [405-814] carrier='Uninor GPRS' apn='uninor' uid='' pwd='' |
| | | [405-815] carrier='Uninor GPRS' apn='uninor' uid='' pwd='' |
| | | [405-816] carrier='Uninor GPRS' apn='uninor' uid='' pwd='' |
| | | [405-817] carrier='Uninor GPRS' apn='uninor' uid='' pwd='' |
| | | [405-818] carrier='Uninor GPRS' apn='uninor' uid='' pwd='' |
| | | [405-819] carrier='Uninor GPRS' apn='uninor' uid='' pwd='' |
| | | [405-820] carrier='Uninor GPRS' apn='uninor' uid='' pwd='' |
| | | [405-821] carrier='Uninor GPRS' apn='uninor' uid='' pwd='' |
| | | [405-822] carrier='Uninor GPRS' apn='uninor' uid='' pwd='' |
| | | [405-823] carrier='Videocon' apn='vinternet.com' uid='' pwd='' |
| | | [405-824] carrier='Videocon' apn='vinternet.com' uid='' pwd='' |
| | | [405-825] carrier='Videocon' apn='vinternet.com' uid='' pwd='' |
| | | [405-826] carrier='Videocon' apn='vinternet.com' uid='' pwd='' |
| | | [405-827] carrier='Videocon' apn='vinternet.com' uid='' pwd='' |
| | | [405-828] carrier='Videocon' apn='vinternet.com' uid='' pwd='' |
| | | [405-829] carrier='Videocon' apn='vinternet.com' uid='' pwd='' |
| | | [405-830] carrier='Videocon' apn='vinternet.com' uid='' pwd='' |
| | | [405-831] carrier='Videocon' apn='vinternet.com' uid='' pwd='' |
| | | [405-832] carrier='Videocon' apn='vinternet.com' uid='' pwd='' |
| | | [405-833] carrier='Videocon' apn='vinternet.com' uid='' pwd='' |
| | | [405-834] carrier='Videocon' apn='vinternet.com' uid='' pwd='' |
| | | [405-835] carrier='Videocon' apn='vinternet.com' uid='' pwd='' |
| | | [405-836] carrier='Videocon' apn='vinternet.com' uid='' pwd='' |
| | | [405-837] carrier='Videocon' apn='vinternet.com' uid='' pwd='' |
| | | [405-838] carrier='Videocon' apn='vinternet.com' uid='' pwd='' |
| | | [405-839] carrier='Videocon' apn='vinternet.com' uid='' pwd='' |
| | | [405-840] carrier='Videocon' apn='vinternet.com' uid='' pwd='' |
| | | [405-841] carrier='Videocon' apn='vinternet.com' uid='' pwd='' |
| | | [405-842] carrier='Videocon' apn='vinternet.com' uid='' pwd='' |
| | | [405-843] carrier='Videocon' apn='vinternet.com' uid='' pwd='' |
| | | [405-844] carrier='Uninor GPRS' apn='uninor' uid='' pwd='' |
| | | [405-845] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [405-846] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [405-847] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [405-848] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [405-849] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [405-850] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [405-851] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [405-852] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [405-853] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [405-875] carrier='Uninor GPRS' apn='uninor' uid='' pwd='' |
| | | [405-876] carrier='Uninor GPRS' apn='uninor' uid='' pwd='' |
| | | [405-877] carrier='Uninor GPRS' apn='uninor' uid='' pwd='' |
| | | [405-878] carrier='Uninor GPRS' apn='uninor' uid='' pwd='' |
| | | [405-879] carrier='Uninor GPRS' apn='uninor' uid='' pwd='' |
| | | [405-880] carrier='Uninor GPRS' apn='uninor' uid='' pwd='' |
| | | [405-881] carrier='STEL' apn='gprs.stel.in' uid='' pwd='' |
| | | [405-882] carrier='STEL' apn='gprs.stel.in' uid='' pwd='' |
| | | [405-883] carrier='STEL' apn='gprs.stel.in' uid='' pwd='' |
| | | [405-884] carrier='STEL' apn='gprs.stel.in' uid='' pwd='' |
| | | [405-885] carrier='STEL' apn='gprs.stel.in' uid='' pwd='' |
| | | [405-886] carrier='STEL' apn='gprs.stel.in' uid='' pwd='' |
| | | [405-908] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [405-909] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [405-910] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [405-911] carrier='IDEA' apn='internet' uid='' pwd='' |
| | | [405-925] carrier='Uninor GPRS' apn='uninor' uid='' pwd='' |
| | | [405-926] carrier='Uninor GPRS' apn='uninor' uid='' pwd='' |
| | | [405-927] carrier='Uninor GPRS' apn='uninor' uid='' pwd='' |
| | | [405-928] carrier='Uninor GPRS' apn='uninor' uid='' pwd='' |
| | | [405-929] carrier='Uninor GPRS' apn='uninor' uid='' pwd='' |
| | | [405-932] carrier='Videocon' apn='vinternet.com' uid='' pwd='' |
| | | [410-01] carrier='Mobilink WAP GPRS' apn='connect.mobilinkworld.com' uid='Mobilink' pwd='Mobilink' |
| | | [410-03] carrier='Ufone WAP' apn='Ufone.internet' uid='' pwd='' |
| | | [410-04] carrier='ZONG WAP' apn='zonginternet' uid='' pwd='' |
| | | [410-06] carrier='Telenor WAP' apn='internet' uid='' pwd='' |
| | | [410-07] carrier='Warid WAP' apn='Wap.warid' uid='' pwd='' |
| | | [415-01] carrier='Alfa Internet' apn='internet.mic1.com.lb' uid='mic1' pwd='mic1' |
| | | [415-03] carrier='MTC Touch GPRS' apn='gprs.mtctouch.com.lb' uid='' pwd='' |
| | | [416-01] carrier='Zain JO Internet Postpaid' apn='internet' uid='' pwd='' |
| | | [416-01] carrier='Zain JO Internet Prepaid' apn='internetpre' uid='zain' pwd='zain' |
| | | [416-03] carrier='umniahinternet Postpaid' apn='internet' uid='' pwd='' |
| | | [416-03] carrier='umniah Prepaid' apn='net' uid='' pwd='' |
| | | [416-77] carrier='Orange Internet' apn='net.orange.jo' uid='net' pwd='net' |
| | | [419-02] carrier='ZAIN MI' apn='pps' uid='pps' pwd='pps' |
| | | [419-03] carrier='INTERNET ACTION' apn='action.wataniya.com' uid='' pwd='' |
| | | [419-04] carrier='VIVA Internet' apn='VIVA' uid='' pwd='' |
| | | [420-01] carrier='JAWALNet' apn='jawalnet.com.sa' uid='' pwd='' |
| | | [420-03] carrier='mobily Net Prepaid' apn='web2' uid='' pwd='' |
| | | [420-03] carrier='mobily Net Postpaid' apn='web1' uid='' pwd='' |
| | | [420-04] carrier='zain-gprs' apn='zain' uid='' pwd='' |
| | | [422-02] carrier='Oman Mobile Internet' apn='taif' uid='taif' pwd='taif' |
| | | [422-03] carrier='Nawras GPRS' apn='isp.nawras.com.om' uid='' pwd='' |
| | | [424-02] carrier='DATA Package' apn='etisalat.ae' uid='' pwd='' |
| | | [424-03] carrier='du' apn='du' uid='' pwd='' |
| | | [425-01] carrier='3G Portal' apn='uwap.orange.co.il' uid='' pwd='' |
| | | [425-01] carrier='Internet 3G' apn='modem.orange.net.il' uid='' pwd='' |
| | | [425-02] carrier='Cellcom Internet' apn='Sphone' uid='' pwd='' |
| | | [425-03] carrier='Sphone Pelephone' apn='sphone.pelephone.net.il' uid='pcl@3g' pwd='pcl' |
| | | [426-01] carrier='Internet' apn='internet.batelco.com' uid='' pwd='' |
| | | [426-02] carrier='Zain Internet' apn='connect.mobilinkworld.com' uid='Mobilink' pwd='Mobilink' |
| | | [426-04] carrier='VIVAGPRS' apn='viva.bh' uid='' pwd='' |
| | | [427-01] carrier='Qtel GPRS' apn='gprs.qtel' uid='gprs' pwd='gprs' |
| | | [427-02] carrier='VFQ Mobile Internet' apn='web.vodafone.com.qa' uid='' pwd='' |
| | | [440-10] carrier='sp???' apn='spmode.ne.jp' uid='' pwd='' |
| | | [440-10] carrier='mopera U(?????????)' apn='mpr2.bizho.net' uid='' pwd='' |
| | | [440-10] carrier='mopera U??' apn='0120.mopera.net' uid='' pwd='' |
| | | [450-05] carrier='SK Telecom (Roaming)' apn='roaming.sktelecom.com' uid='' pwd='' |
| | | [450-05] carrier='SK Telecom' apn='web.sktelecom.com' uid='' pwd='' |
| | | [450-08] carrier='KT-HSDPA' apn='alwayson-r6.ktfwing.com' uid='' pwd='' |
| | | [452-04] carrier='Viettel Email' apn='v-internet' uid='' pwd='' |
| | | [452-05] carrier='Vietnamobile Email' apn='internet' uid='' pwd='' |
| | | [452-07] carrier='BEELINE Email' apn='internet' uid='' pwd='' |
| | | [452-08] carrier='EVNTelecom Email' apn='e-internet' uid='' pwd='' |
| | | [454-00] carrier='CSL Data' apn='hkcsl' uid='' pwd='' |
| | | [454-02] carrier='CSL Data' apn='hkcsl' uid='' pwd='' |
| | | [454-03] carrier='3' apn='mobile.three.com.hk' uid='' pwd='' |
| | | [454-04] carrier='3-DB-GPRS' apn='web-g.three.com.hk' uid='' pwd='' |
| | | [454-06] carrier='SmarTone HK' apn='SmarTone' uid='' pwd='' |
| | | [454-10] carrier='CSL Data' apn='hkcsl' uid='' pwd='' |
| | | [454-12] carrier='CMHK GPRS' apn='peoples.net' uid='' pwd='' |
| | | [454-16] carrier='PCCW_GPRS' apn='pccwdata' uid='' pwd='' |
| | | [454-18] carrier='CSL Data' apn='hkcsl' uid='' pwd='' |
| | | [454-19] carrier='PCCW 3G' apn='pccw' uid='' pwd='' |
| | | [455-00] carrier='SmarTone MAC' apn='smartgprs' uid='' pwd='' |
| | | [455-01] carrier='CTM' apn='ctm-mobile' uid='' pwd='' |
| | | [455-03] carrier='3 Macau' apn='web-g.three.com.hk' uid='hutchison' pwd='1234' |
| | | [455-04] carrier='CTM' apn='ctm-mobile' uid='' pwd='' |
| | | [460-00] carrier='China Mobile' apn='cmnet' uid='' pwd='' |
| | | [460-01] carrier='China Unicom' 3g_apn='3gnet' 3g_uid='' 3g_pwd='' apn='uninet' uid='' pwd='' |
| | | [460-02] carrier='China Mobile' apn='cmnet' uid='' pwd='' |
| | | [460-03] carrier='China Telecom' apn='ctnet' uid='' pwd='' |
| | | [460-07] carrier='China Mobile' apn='cmnet' uid='' pwd='' |
| | | [466-01] carrier='????(Far EasTone) (Internet)' apn='internet' uid='' pwd='' |
| | | [466-88] carrier='????(KGT-Online) (Internet)' apn='internet' uid='' pwd='' |
| | | [466-89] carrier='????(VIBO)' apn='vibo' uid='' pwd='' |
| | | [466-92] carrier='????(Chunghwa) (Internet)' apn='internet' uid='' pwd='' |
| | | [466-92] carrier='????(Chunghwa)' apn='emome' uid='' pwd='' |
| | | [466-93] carrier='?????(TW Mobile) (Internet)' apn='internet' uid='' pwd='' |
| | | [466-93] carrier='?????(TW Mobile) (twm)' apn='TWM' uid='' pwd='' |
| | | [466-97] carrier='?????(TW Mobile) (Internet)' apn='internet' uid='' pwd='' |
| | | [466-97] carrier='?????(TW Mobile) (twm)' apn='TWM' uid='' pwd='' |
| | | [466-99] carrier='?????(TW Mobile) (Internet)' apn='internet' uid='' pwd='' |
| | | [466-99] carrier='?????(TW Mobile) (twm)' apn='TWM' uid='' pwd='' |
| | | [502-12] carrier='Maxis 3G Internet' 3g_apn='unet' 3g_uid='maxis' 3g_pwd='wap' apn='net' uid='maxis' pwd='wap' |
| | | [502-16] carrier='DiGi Internet' 3g_apn='diginet' 3g_uid='' 3g_pwd='' apn='diginet' uid='' pwd='' |
| | | [502-18] carrier='U Mobile Internet' 3g_apn='my3g' 3g_uid='' 3g_pwd='' apn='my3g' uid='' pwd='' |
| | | [502-19] carrier='Celcom 3G Internet' 3g_apn='celcom3g' 3g_uid='' 3g_pwd='' apn='celcom.net.my' uid='' pwd='' |
| | | [505-01] carrier='Telstra Internet' apn='telstra.wap' uid='' pwd='' |
| | | [505-02] carrier='Optus Yes Internet' apn='yesinternet' uid='' pwd='' |
| | | [505-03] carrier='Vodafone live!' apn='live.vodafone.com' uid='' pwd='' |
| | | [505-06] carrier='Planet 3' apn='3services' uid='' pwd='' |
| | | [505-07] carrier='VF AU PXT' apn='live.vodafone.com' uid='' pwd='' |
| | | [505-07] carrier='VF Internet' apn='vfinternet.au' uid='' pwd='' |
| | | [505-11] carrier='Telstra Internet' apn='Telstra.wap' uid='' pwd='' |
| | | [505-12] carrier='3Internet' apn='3netaccess' uid='' pwd='' |
| | | [505-12] carrier='3' apn='3services' uid='' pwd='' |
| | | [505-71] carrier='Telstra Internet' apn='Telstra.wap' uid='' pwd='' |
| | | [505-72] carrier='Telstra Internet' apn='Telstra.wap' uid='' pwd='' |
| | | [505-88] carrier='VF AU PXT' apn='live.vodafone.com' uid='' pwd='' |
| | | [505-88] carrier='VF Internet' apn='vfinternet.au' uid='' pwd='' |
| | | [505-90] carrier='Optus Internet' apn='internet' uid='' pwd='' |
| | | [510-01] carrier='ISAT BB INTERNET' apn='indosat3g' uid='indosat' pwd='indosat' |
| | | [510-01] carrier='ISAT WAP' apn='indosatgprs' uid='indosat' pwd='indosat' |
| | | [510-08] carrier='AXISinternet' apn='AXIS' uid='AXIS' pwd='123456' |
| | | [510-10] carrier='Telkomsel GPRS WEB' apn='internet' uid='wap' pwd='wap123' |
| | | [510-11] carrier='XL GPRS' apn='www.xlgprs.net' uid='xlgprs' pwd='proxl' |
| | | [510-11] carrier='XL Unlimited' apn='xlunlimited' uid='' pwd='' |
| | | [510-21] carrier='ISAT M3 INTERNET' apn='indosatgprs' uid='indosat' pwd='indosat' |
| | | [510-89] carrier='3 GPRS' apn='3gprs' uid='3gprs' pwd='3gprs' |
| | | [515-02] carrier='myGlobe Internet Postpaid' apn='internet.globe.com.ph' uid='' pwd='' |
| | | [515-02] carrier='myGlobe Internet Prepaid' apn='http.globe.com.ph' uid='' pwd='' |
| | | [515-03] carrier='Smart Internet' apn='internet' uid='' pwd='' |
| | | [515-05] carrier='SUN INTERNET' apn='minternet' uid='' pwd='' |
| | | [515-18] carrier='RED INTERNET' apn='redinternet' uid='' pwd='' |
| | | [520-01] carrier='AIS Internet' apn='internet' uid='' pwd='' |
| | | [520-18] carrier='DTAC Internet' apn='www.dtac.co.th' uid='' pwd='' |
| | | [520-99] carrier='True GPRS Inet' apn='internet' uid='TRUE' pwd='TRUE' |
| | | [525-01] carrier='IDEAS E-mail' apn='e-ideas' uid='' pwd='' |
| | | [525-02] carrier='IDEAS E-mail' apn='e-ideas' uid='' pwd='' |
| | | [525-03] carrier='M1 E-mail' apn='sunsurf' uid='65' pwd='' |
| | | [525-05] carrier='StarHub' apn='internet' uid='' pwd='' |
| | | [525-05] carrier='Gee!' apn='shwap' uid='star' pwd='hub' |
| | | [525-05] carrier='StarHub E-mail' apn='shwap' uid='' pwd='' |
| | | [530-01] carrier='VFNZ PXT' apn='live.vodafone.com' uid='' pwd='' |
| | | [530-01] carrier='VFNZ Internet' apn='www.vodafone.net.nz' uid='' pwd='' |
| | | [530-05] carrier='TelecomDefault' apn='wap.telecom.co.nz' uid='' pwd='' |
| | | [530-24] carrier='2degrees Internet' apn='internet' uid='' pwd='' |
| | | [602-01] carrier='Mobinil Web' apn='MobinilWeb' uid='' pwd='' |
| | | [602-02] carrier='VF internet' apn='internet.vodafone.net' uid='internet' pwd='internet' |
| | | [602-03] carrier='Etisalat internet' apn='Etisalat' uid='' pwd='' |
| | | [605-01] carrier='weborange' apn='weborange' uid='' pwd='' |
| | | [605-02] carrier='mobinet' apn='gprs.tn' uid='gprs' pwd='gprs' |
| | | [605-03] carrier='internet Tunisiana' apn='internet.tunisiana.com' uid='internet' pwd='internet' |
| | | [621-20] carrier='Zain Mobile Internet' apn='internet.ng.Zain.com' uid='' pwd='' |
| | | [621-30] carrier='MTN GPRS' apn='web.gprs.mtnnigeria.net' uid='web' pwd='web' |
| | | [621-50] carrier='glo direct' apn='glosecure' uid='gprs' pwd='gprs' |
| | | [621-60] carrier='Etisalat Internet' apn='etisalat' uid='' pwd='' |
| | | [639-02] carrier='SafaricomBrowse' apn='Safaricom' uid='saf' pwd='data' |
| | | [639-03] carrier='Zain WAP' apn='wap.ke.celtel.com' uid='wap' pwd='wap' |
| | | [639-07] carrier='Orange Internet' apn='wap.orange.co.ke' uid='' pwd='' |
| | | [640-04] carrier='Vodacom WAP' apn='Wap' uid='' pwd='' |
| | | [647-00] carrier='Orange World re' apn='orangerun' uid='orange' pwd='orange' |
| | | [647-10] carrier='GPRS SRR' apn='wapsfr' uid='wap' pwd='wap' |
| | | [651-01] carrier='VCL Internet GPRS' apn='internet' uid='' pwd='' |
| | | [655-01] carrier='Vodacom' apn='internet' uid='' pwd='' |
| | | [655-02] carrier='8.ta internet' apn='internet' uid='' pwd='' |
| | | [655-07] carrier='Smartdata' apn='internet' uid='' pwd='' |
| | | [655-07] carrier='virgin_internet' apn='vdata' uid='' pwd='' |
| | | [655-10] carrier='MTN Data' apn='myMTN' uid='mtn' pwd='' |
| | | [704-01] carrier='INTERNET CLARO' apn='internet.ideasclaro' uid='' pwd='' |
| | | [704-02] carrier='BROADBAND TIGO' apn='broadband.tigo.gt' uid='' pwd='' |
| | | [704-03] carrier='Internet GT' apn='internet.movistar.gt' uid='movistargt' pwd='movistargt' |
| | | [704-30] carrier='Internet GT' apn='internet.movistar.gt' uid='movistargt' pwd='movistargt' |
| | | [706-01] carrier='INTERNET CLARO' apn='internet.ideasclaro' uid='' pwd='' |
| | | [706-02] carrier='El Salvaldor Digicel' apn='web.digicelsv.com' uid='' pwd='' |
| | | [706-03] carrier='BROADBAND TIGO' apn='broadband.tigo.sv' uid='' pwd='' |
| | | [706-04] carrier='Internet SV' apn='internet.movistar.sv' uid='movistarsv' pwd='movistarsv' |
| | | [706-40] carrier='Internet SV' apn='internet.movistar.sv' uid='movistarsv' pwd='movistarsv' |
| | | [708-01] carrier='Internet Claro' apn='web.megatel.hn' uid='webmegatel' pwd='webmegatel' |
| | | [708-02] carrier='INTERNET TIGO' apn='internet.tigo.hn' uid='' pwd='' |
| | | [708-20] carrier='INTERNET TIGO' apn='internet.tigo.hn' uid='' pwd='' |
| | | [710-21] carrier='INTERNET' apn='web.emovil' uid='webemovil' pwd='webemovil' |
| | | [710-300] carrier='Internet GPRS' apn='internet.movistar.ni' uid='movistarni' pwd='movistarni' |
| | | [710-730] carrier='INTERNET' apn='web.emovil' uid='webemovil' pwd='webemovil' |
| | | [712-01] carrier='Kolbi' apn='kolbi3g' uid='' pwd='' |
| | | [712-01] carrier='Multimedia' apn='kolbi3g' uid='' pwd='' |
| | | [712-02] carrier='Kolbi' apn='kolbi3g' uid='' pwd='' |
| | | [712-02] carrier='Multimedia' apn='kolbi3g' uid='' pwd='' |
| | | [712-03] carrier='INTERNET CLARO' apn='internet.ideasclaro' uid='' pwd='' |
| | | [712-04] carrier='movistar INTERNET' apn='internet.movistar.cr' uid='movistarcr' pwd='movistarcr' |
| | | [714-01] carrier='Wap' apn=' apn01.cwpanama.com.pa' uid='' pwd='' |
| | | [714-01] carrier='Mms' apn=' apn02.cwpanama.com.pa' uid='' pwd='' |
| | | [714-20] carrier='movistar INTERNET' apn='internet.movistar.pa' uid='movistarpa' pwd='movistarpa' |
| | | [714-03] carrier='WEB Claro' apn='web.claro.com.pa' uid='CLAROWEB' pwd='CLAROWEB' |
| | | [714-04] carrier='INTERNET Panama' apn='web.digicelpanama.com' uid='' pwd='' |
| | | [716-06] carrier='movistar Internet' apn='movistar.pe' uid='movistar@datos' pwd='movistar' |
| | | [716-10] carrier='CLARO DATOS' apn='claro.pe' uid='claro' pwd='claro' |
| | | [722-07] carrier='Movistar Emoción' apn='wap.gprs.unifon.com.ar' uid='wap' pwd='wap' |
| | | [722-31] carrier='Claro AR' apn='igprs.claro.com.ar' uid='ctigprs' pwd='ctigprs999' |
| | | [722-310] carrier='Claro AR' apn='igprs.claro.com.ar' uid='ctigprs' pwd='ctigprs999' |
| | | [722-34] carrier='Personal Datos' apn='datos.personal.com' uid='gprs' pwd='adgj' |
| | | [722-341] carrier='Personal Datos' apn='datos.personal.com' uid='gprs' pwd='adgj' |
| | | [724-02] carrier='TIM Connect' apn='timbrasil.br' uid='tim' pwd='tim' |
| | | [724-03] carrier='TIM Connect' apn='timbrasil.br' uid='tim' pwd='tim' |
| | | [724-04] carrier='TIM Connect' apn='timbrasil.br' uid='tim' pwd='tim' |
| | | [724-05] carrier='Java Session' apn='java.claro.com.br' uid='claro' pwd='claro' |
| | | [724-06] carrier='Vivo Internet' apn='zap.vivo.com.br' uid='vivo' pwd='vivo' |
| | | [724-07] carrier='SCTL GPRS' apn='sercomtel.com.br' uid='sercomtel' pwd='sercomtel' |
| | | [724-10] carrier='Vivo Internet' apn='zap.vivo.com.br' uid='vivo' pwd='vivo' |
| | | [724-11] carrier='Vivo Internet' apn='zap.vivo.com.br' uid='vivo' pwd='vivo' |
| | | [724-16] carrier='BrT Modem' apn='brt.br' uid='brt' pwd='brt' |
| | | [724-19] carrier='TelemigC GPRS' apn='gprs.telemigcelular.com.br' uid='celular' pwd='celular' |
| | | [724-23] carrier='Vivo Internet' apn='zap.vivo.com.br' uid='vivo' pwd='vivo' |
| | | [724-24] carrier='AmazôniaC GPRS' apn='gprs.amazoniacelular.com.br' uid='celular' pwd='celular' |
| | | [724-31] carrier='OI GPRS' apn='gprs.oi.com.br' uid='' pwd='' |
| | | [730-01] carrier='Internet Movil' apn='bam.entelpcs.cl' uid='entelpcs' pwd='entelpcs' |
| | | [730-10] carrier='Internet Movil' apn='bam.entelpcs.cl' uid='entelpcs' pwd='entelpcs' |
| | | [730-02] carrier='NEM' apn='wap.tmovil.cl' uid='wap' pwd='wap' |
| | | [730-03] carrier='BAM Claro' apn='bam.clarochile.cl' uid='clarochile' pwd='clarochile' |
| | | [730-07] carrier='web' apn='web.gtdmovil.cl' uid='webgtd' pwd='webgtd' |
| | | [730-08] carrier='Internet' apn='movil.vtr.com' uid='vtrmovil' pwd='vtrmovil' |
| | | [730-08] carrier='Wap' apn='wap.vtr.com' uid='' pwd='' |
| | | [730-08] carrier='Bam' apn='bam.vtr.com' uid='vtr' pwd='vtr' |
| | | [730-10] carrier='Internet Movil' apn='bam.entelpcs.cl' uid='entelpcs' pwd='entelpcs' |
| | | [732-101] carrier='WEB Comcel 3GSM' apn='internet.comcel.com.co' uid='COMCELWEB' pwd='COMCELWEB' |
| | | [732-103] carrier='TIGO WEB' apn='web.colombiamovil.com.co' uid='' pwd='' |
| | | [732-111] carrier='TIGO WEB' apn='web.colombiamovil.com.co' uid='' pwd='' |
| | | [732-123] carrier='movistar INTERNET' apn='internet.movistar.com.co' uid='movistar' pwd='movistar' |
| | | [734-01] carrier='Digitel GSM' apn='gprsweb.digitel.ve' uid='' pwd='' |
| | | [734-02] carrier='Digitel GSM' apn='gprsweb.digitel.ve' uid='' pwd='' |
| | | [734-03] carrier='Digitel GSM' apn='gprsweb.digitel.ve' uid='' pwd='' |
| | | [734-04] carrier='movistar INTERNET' apn='internet.movistar.ve' uid='' pwd='' |
| | | [734-04] carrier='movistar WAP' apn='wap.movistar.ve' uid='' pwd='' |
| | | [734-06] carrier='MODEM' apn='int.movilnet.com.ve' uid='' pwd='' |
| | | [736-01] carrier='VIVA3G' apn='internet.nuevatel.com' uid='' pwd='' |
| | | [736-02] carrier='ENTEL WAP GPRS' apn='wap.movil.com.bo' uid='' pwd='' |
| | | [736-03] carrier='WAPTIGO' apn='wap.tigo.bo' uid='' pwd='' |
| | | [740-00] carrier='movistar INTERNET' apn='internet.movistar.com.ec' uid='movistar' pwd='movistar' |
| | | [740-01] carrier='Claro Internet' apn='internet.porta.com.ec' uid='' pwd='' |
| | | [740-10] carrier='Claro Internet' apn='internet.porta.com.ec' uid='' pwd='' |
| | | [740-02] carrier='ALEGRO 3G' apn='internet3gsp.alegro.net.ec' uid='' pwd='' |
| | | [744-01] carrier='VOX INTERNET' apn='vox.internet' uid='' pwd='' |
| | | [744-02] carrier='Claro PY' apn='igprs.claro.com.py' uid='ctigprs' pwd='ctigprs999' |
| | | [744-04] carrier='TIGO PY' apn='internet.tigo.py' uid='' pwd='' |
| | | [744-05] carrier='Personal Datos Py' apn='internet' uid='personal' pwd='personal' |
| | | [748-01] carrier='wapANCEL' apn='wap' uid='' pwd='' |
| | | [748-01] carrier='gprsANCEL' apn='gprs.ancel' uid='' pwd='' |
| | | [748-07] carrier='Movistar Emoción' apn='webapn.movistar.com.uy' uid='movistar' pwd='movistar' |
| | | [748-10] carrier='Claro UY' apn='igprs.claro.com.uy' uid='ctigprs' pwd='ctigprs999' |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: fw_entry.c |
| | | * Description: This is the FWE(FL2440 Worker Engine) applets(such as gsmd, |
| | | * gpsd, zigbeed) main entry point function. |
| | | * |
| | | * Version: 1.0.0(01/13/2013~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "01/13/2013 02:40:36 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include "fwe_entry.h" |
| | | #include "gsmd.h" |
| | | #include "gpsd.h" |
| | | #include "zigd.h" |
| | | |
| | | FWE_APPLET applets_list[] = |
| | | { |
| | | {"gsmd", gsmd_main}, |
| | | {"gpsd", gpsd_main}, |
| | | {"zigd", zigd_main}, |
| | | {0, 0} |
| | | }; |
| | | |
| | | static void entry_usage(void); |
| | | static void print_applist(void); |
| | | |
| | | int main(int argc, char **argv) |
| | | { |
| | | FWE_APPLET *app = NULL; |
| | | const char *applet_name = NULL; |
| | | int ind = 0; |
| | | |
| | | applet_name = basename(argv[0]); |
| | | |
| | | /* Run command like "FWE gsmd" */ |
| | | if( !strncmp(applet_name, FWE_ENTRY_NAME, 4) ) |
| | | { |
| | | if(argv[1] && argv[1][0]!='-') |
| | | { |
| | | applet_name = basename(argv[1]); |
| | | ind = 1; |
| | | } |
| | | else |
| | | { |
| | | entry_usage(); |
| | | return 0; |
| | | } |
| | | } |
| | | |
| | | for(app=(FWE_APPLET *)&applets_list; app->name; app++) |
| | | { |
| | | if(!strcmp (app->name, applet_name) && app->main) |
| | | { |
| | | return app->main(argc-ind, argv+ind); |
| | | } |
| | | } |
| | | |
| | | printf("%s: applet not found\n\n", applet_name); |
| | | print_applist(); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | static void print_applist(void) |
| | | { |
| | | FWE_APPLET *app; |
| | | |
| | | printf("Currently defined applets:\n"); |
| | | for(app=(FWE_APPLET *)&applets_list; app->name; app++) |
| | | { |
| | | printf("%s ", app->name); |
| | | } |
| | | printf("\n"); |
| | | } |
| | | |
| | | /* Just print the help information */ |
| | | static void entry_usage(void) |
| | | { |
| | | banner(FWE_ENTRY_NAME); |
| | | |
| | | printf("Usage: %s [applet] [arguments]...\n", FWE_ENTRY_NAME); |
| | | printf(" or: applet [arguments]...\n"); |
| | | |
| | | printf("\n\t%s is a multi-call binary that combines many FL2440 Work Engine(FWE) applets\n", FWE_ENTRY_NAME); |
| | | printf("\tinto a single executable. We can create a symbolic link to %s for each applet\n",FWE_ENTRY_NAME); |
| | | printf("\tlike busybox work.\n\n"); |
| | | |
| | | print_applist(); |
| | | printf("\n"); |
| | | |
| | | return ; |
| | | } |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2013 Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: fwe_entry.h |
| | | * Description: This head file |
| | | * |
| | | * Version: 1.0.0(01/13/2013~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "01/13/2013 02:53:41 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #ifndef __FWE_ENTRY_H_ |
| | | #define __FWE_ENTRY_H_ |
| | | |
| | | #include <stdio.h> |
| | | #include <stdint.h> |
| | | #include <stdlib.h> |
| | | #include <stdarg.h> |
| | | #include <stddef.h> |
| | | #include <string.h> |
| | | #include <pthread.h> |
| | | |
| | | #include "version.h" |
| | | |
| | | #define FWE_ENTRY_NAME "fwed" |
| | | |
| | | typedef int (APPLET_MAIN)(int argc, char **argv); |
| | | |
| | | typedef struct __FWE_APPLET |
| | | { |
| | | char *name; |
| | | APPLET_MAIN *main; |
| | | } FWE_APPLET; |
| | | |
| | | |
| | | |
| | | #endif /* end of __FWE_ENTRY_H_ */ |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) Guo Wenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: gpsd.c |
| | | * Description: This is the RWME(Radiation Monitor Works Engine) gpsd applet entry point |
| | | * |
| | | * Version: 1.0.0(01/13/2013~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "01/13/2013 02:40:36 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | #include "gpsd.h" |
| | | #include "cp_hal.h" |
| | | #include "cp_time.h" |
| | | |
| | | static void usage_gpsd(const char *progname) |
| | | { |
| | | banner(progname); |
| | | |
| | | printf("Usage: %s [OPTION]...\n", progname); |
| | | printf(" %s is a daemon program running on the device to locate the device\n", progname); |
| | | |
| | | printf("\nMandatory arguments to long options are mandatory for short options too:\n"); |
| | | printf(" -d[debug ] Running in debug mode\n"); |
| | | printf(" -l[level ] Set the log level as [0..%d]\n", LOG_LEVEL_MAX-1); |
| | | printf(" -h[help ] Display this help information\n"); |
| | | printf(" -v[version ] Display the program version\n"); |
| | | |
| | | return; |
| | | } |
| | | |
| | | int init_gpsd_context(GPSD_CONTEX *gps) |
| | | { |
| | | log_info("Initialize gpsd context.\n"); |
| | | |
| | | gps->pwr_status = POWER_OFF; |
| | | |
| | | nmea_zero_INFO(&(gps->info)); |
| | | |
| | | /* Initialize the GPS dataport pointer */ |
| | | gps->comport = comport_init(GPS_DATAPORT, 9600, "8N1N"); |
| | | if(NULL == gps->comport) |
| | | { |
| | | log_err("Initialise GPS data port %s on 9600 with 8N1N failure\n", GPS_DATAPORT); |
| | | return -1; |
| | | } |
| | | |
| | | if( comport_open(gps->comport) < 0) |
| | | { |
| | | log_err("Open GPS data port %s on 9600 with 8N1N failure\n", GPS_DATAPORT); |
| | | return -2; |
| | | } |
| | | |
| | | log_dbg("Open GPS data port %s on 9600 with 8N1N successfully\n", GPS_DATAPORT); |
| | | return 0; |
| | | } |
| | | |
| | | void term_gpsd_context(GPSD_CONTEX *gps) |
| | | { |
| | | comport_term(gps->comport); |
| | | |
| | | #if 0 |
| | | if( ON== hal_get_gps_power()) |
| | | { |
| | | hal_turn_gps_power(OFF); |
| | | } |
| | | #endif |
| | | |
| | | return ; |
| | | } |
| | | |
| | | |
| | | |
| | | int start_gpsd_service(GPSD_CONTEX *gps) |
| | | { |
| | | int len; |
| | | char buf[1024]; |
| | | |
| | | while( !g_cp_signal.stop ) |
| | | { |
| | | if( OFF== (gps->pwr_status=hal_get_gps_power()) ) |
| | | { |
| | | hal_turn_gps_power(ON); |
| | | continue; |
| | | } |
| | | |
| | | memset(buf, 0, sizeof(buf)); |
| | | if( (len=comport_recv(gps->comport, buf, sizeof(buf), 3000)) > 0) |
| | | { |
| | | /* Data sample: |
| | | * $GPGGA,081803.000,3029.9100,N,11423.2012,E,1,05,1.6,38.7,M,-13.7,M,,0000*4C |
| | | * $GPGSA,A,3,18,24,21,22,15,,,,,,,,3.1,1.6,2.7*3A |
| | | * $GPRMC,081803.000,A,3029.9100,N,11423.2012,E,1.14,126.38,210113,,,A*62 |
| | | */ |
| | | nmea_parse(buf, len, &(gps->info)); |
| | | log_nrml("GPS get UTC time: %d-%d-%d %d:%d:%d.%d\n", gps->info.utc.year+1900, gps->info.utc.mon+1, gps->info.utc.day, |
| | | gps->info.utc.hour+8, gps->info.utc.min, gps->info.utc.sec, gps->info.utc.hsec); |
| | | log_nrml("GPS Sig[%d] Latitude:[%f] Longitude:[%f]\n", gps->info.sig, gps->info.lat, gps->info.lon); |
| | | } |
| | | |
| | | micro_second_sleep(100); |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int gpsd_main(int argc, char **argv) |
| | | { |
| | | int opt; |
| | | int rv = 0; |
| | | int debug = 0; |
| | | char pid_file[64] = { 0 }; /* The file used to record the PID */ |
| | | const char *progname=NULL; |
| | | char *log_file = GPSD_DEF_LOG_FILE; |
| | | int log_level = GPSD_DEF_LOG_LEVEL; |
| | | cp_logger *logger = NULL; |
| | | GPSD_CONTEX gpsd_ctx; |
| | | |
| | | struct option long_options[] = { |
| | | {"debug", no_argument, NULL, 'd'}, |
| | | {"level", required_argument, NULL, 'l'}, |
| | | {"version", no_argument, NULL, 'v'}, |
| | | {"help", no_argument, NULL, 'h'}, |
| | | {NULL, 0, NULL, 0} |
| | | }; |
| | | |
| | | progname = basename(argv[0]); |
| | | |
| | | /* Parser the command line parameters */ |
| | | while ((opt = getopt_long(argc, argv, "dl:vh", long_options, NULL)) != -1) |
| | | { |
| | | switch (opt) |
| | | { |
| | | case 'd': /* Set debug running */ |
| | | debug = 1; |
| | | log_file = DBG_LOG_FILE; |
| | | break; |
| | | |
| | | case 'l': /* Set the log level */ |
| | | log_level = atoi(optarg); |
| | | break; |
| | | |
| | | case 'v': /* Get software version */ |
| | | banner(progname); /* Defined in version.h */ |
| | | return EXIT_SUCCESS; |
| | | |
| | | case 'h': /* Get help information */ |
| | | usage_gpsd(progname); |
| | | return 0; |
| | | |
| | | default: |
| | | break; |
| | | } /* end of "switch(opt)" */ |
| | | } |
| | | |
| | | if( !debug ) |
| | | { |
| | | snprintf(pid_file, sizeof(pid_file), "%s/%s.pid", PID_FILE_PATH, progname); |
| | | if( check_daemon_running(pid_file) ) |
| | | { |
| | | printf("Programe already running, exit now.\n"); |
| | | return -1; |
| | | } |
| | | } |
| | | |
| | | if ( !(logger=cp_log_init(NULL, log_file, log_level, GPSD_LOG_FILE_SIZE)) ) |
| | | { |
| | | printf("Logger initialize failure with file: %s\n", logger->file); |
| | | return -1; |
| | | } |
| | | |
| | | if ( cp_log_open() ) |
| | | { |
| | | printf("Logger initialize failure with file: %s\n", logger->file); |
| | | return -1; |
| | | } |
| | | |
| | | if( !debug ) |
| | | { |
| | | if( set_daemon_running(pid_file) ) |
| | | { |
| | | log_fatal("Set program \"%s\" running as daemon failure.\n", progname); |
| | | goto CleanUp; |
| | | } |
| | | } |
| | | |
| | | cp_install_proc_signal(); |
| | | |
| | | if( init_gpsd_context(&gpsd_ctx) < 0 ) |
| | | { |
| | | log_fatal("Initialise gpsd work context failure, rv=%d\n", rv); |
| | | goto CleanUp; |
| | | } |
| | | |
| | | /* Start the GPS thread to locate the device */ |
| | | if( (rv=start_gpsd_service(&gpsd_ctx)) < 0) |
| | | { |
| | | log_fatal("Start PPP thread failure, rv=%d\n", rv); |
| | | goto CleanUp; |
| | | } |
| | | |
| | | CleanUp: |
| | | log_nrml("Terminate program \"%s\".\n", progname); |
| | | term_gpsd_context(&gpsd_ctx); |
| | | unlink(pid_file); |
| | | cp_log_term(); |
| | | return rv; |
| | | } |
| | | |
| | | |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) guowenxue<guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: gpsd.h |
| | | * Description: This is the rmwe(Radiation Moniter Worker Engine) gpsd applet head file |
| | | * |
| | | * Version: 1.0.0(02/02/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "02/02/2012 11:33:33 AM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #ifndef __GPSD_H_ |
| | | #define __GPSD_H_ |
| | | |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <unistd.h> |
| | | #include <getopt.h> |
| | | #include <sys/types.h> |
| | | #include <signal.h> |
| | | |
| | | #include "cp_comport.h" |
| | | #include "cp_logger.h" |
| | | #include "cp_proc.h" |
| | | #include "nmea_info.h" |
| | | #include "version.h" |
| | | |
| | | #ifndef PID_FILE_PATH |
| | | #define PID_FILE_PATH "/var/run/" |
| | | #endif |
| | | |
| | | #define GPSD_DEF_LOG_FILE "/logs/gpsd.log" |
| | | #define GPSD_DEF_LOG_LEVEL LOG_LEVEL_NRML |
| | | #define GPSD_LOG_FILE_SIZE 12 /* Unit KiByte */ |
| | | |
| | | #define GPS_DATAPORT "/dev/ttyS4" |
| | | |
| | | #define POWER_OFF 0 |
| | | #define POWER_ON 1 |
| | | |
| | | typedef struct __GPSD_CONTEX |
| | | { |
| | | unsigned char pwr_status; |
| | | nmeaINFO info; |
| | | COM_PORT *comport; |
| | | } GPSD_CONTEX; |
| | | |
| | | extern int gpsd_main(int argc, char **argv); |
| | | |
| | | #endif /* End of __GPSD_H_ */ |
New file |
| | |
| | | #********************************************************************************* |
| | | # Copyright: (C) Guo Wenxue<guowenxue@gmail.com> |
| | | # All rights reserved. |
| | | # |
| | | # Filename: Makefile |
| | | # Description: This is the common subdir Makefile which to compile all the C |
| | | # source code to object files and then generate the shared or |
| | | # static library named lib$(FOLDER_NAME).a orlib $(FOLDER_NAME).so, |
| | | # which depends on the variable $LINK_MODE. |
| | | # |
| | | # Version: 1.0.0(01/13/2013~) |
| | | # Author: Guo Wenxue <guowenxue@gmail.com> |
| | | # ChangeLog: 1, Release initial version on "Sun Jan 13 14:44:36 CST 2013" |
| | | # |
| | | #********************************************************************************/ |
| | | |
| | | PWD=$(shell pwd) |
| | | |
| | | #If wanna compile in the subdir, not called by top makefile, uncomment it |
| | | ifneq (${TOP_COMPILE}, YES) |
| | | LOCAL_COMPILE=YES |
| | | endif |
| | | |
| | | LIBNAME=$(shell basename ${PWD}) |
| | | STALIB=lib${LIBNAME}.a |
| | | DYNLIB=lib${LIBNAME}.so |
| | | |
| | | VPATH= . |
| | | SRCS = $(wildcard ${VPATH}/*.c) |
| | | OBJS = $(patsubst %.c,%.o,$(SRCS)) |
| | | |
| | | #====================================================== |
| | | # ---> Doesn't call by top makefile, compile by local |
| | | #====================================================== |
| | | ifeq (${LOCAL_COMPILE}, YES) |
| | | #ARCH?=arm926t |
| | | ARCH?=i386 |
| | | CFLAGS+=-fPIC |
| | | TMP=$(shell echo $(ARCH) | tr "[A-Z]" "[a-z]") |
| | | ifneq (,$(filter i386,$(TMP))) |
| | | CROSS_COMPILE= |
| | | else |
| | | CROSS_COMPILE=/opt/xtools/arm920t/bin/arm-linux- |
| | | endif |
| | | |
| | | PRJDIR?=$(shell dirname ${PWD}) |
| | | CFLAGS+=-I${PRJDIR} |
| | | CC = ${CROSS_COMPILE}gcc |
| | | AR = ${CROSS_COMPILE}ar |
| | | |
| | | endif #End local compile |
| | | |
| | | ifeq ("${LINK_MODE}", "STATIC") |
| | | LIBS = ${STALIB} |
| | | else |
| | | LIBS=${DYNLIB} |
| | | endif |
| | | |
| | | all: entry ${LIBS} install |
| | | |
| | | entry: |
| | | @echo " "; |
| | | @echo " ========================================================="; |
| | | @echo " ** Compile subdir ${LIBNAME} for ${ARCH} "; |
| | | @echo " ========================================================="; |
| | | |
| | | #$(LD) -g --relocatable $(OBJS) -o lib${LIBNAME}.o |
| | | ${STALIB}: $(OBJS) |
| | | $(AR) -rcu $@ $(OBJS) |
| | | |
| | | ${DYNLIB}: $(OBJS) |
| | | $(CC) -fPIC -shared -o $@ $(OBJS) |
| | | |
| | | %.o : %.c |
| | | $(CC) -c $< $(CFLAGS) |
| | | |
| | | tag: |
| | | @ctags --c-kinds=+defglmnstuvx --langmap=c:.c.h.ho.hem.het.hec.hev.him.hit.hic.hiv -R . |
| | | @cscope -Rbq |
| | | |
| | | install: |
| | | @if [ ! -z "${LIBS_PATH}" ] ; then \ |
| | | mkdir -p ${LIBS_PATH} ; \ |
| | | cp ${LIBS} ${LIBS_PATH}; \ |
| | | fi; |
| | | |
| | | |
| | | clean: |
| | | @rm -f *.o |
| | | @rm -rf *.gdb *.a *.so |
| | | |
| | | distclean: clean |
| | | @rm -f tags cscope* |
| | | |
| | | .PHONY: clean entry |
New file |
| | |
| | | /* |
| | | * |
| | | * NMEA library |
| | | * URL: http://nmea.sourceforge.net |
| | | * Author: Tim (xtimor@gmail.com) |
| | | * Licence: http://www.gnu.org/licenses/lgpl.html |
| | | * $Id: sentence.c 17 2008-03-11 11:56:11Z xtimor $ |
| | | * |
| | | */ |
| | | |
| | | #include <stdlib.h> |
| | | #include <string.h> |
| | | #include <time.h> |
| | | #include <stdio.h> |
| | | |
| | | #include "nmea_parse.h" |
| | | #include "nmea_info.h" |
| | | #include "cp_logger.h" |
| | | |
| | | void nmea_zero_GPGGA(nmeaGPGGA *pack) |
| | | { |
| | | memset(pack, 0, sizeof(nmeaGPGGA)); |
| | | nmea_time_now(&pack->utc); |
| | | pack->ns = 'N'; |
| | | pack->ew = 'E'; |
| | | pack->elv_units = 'M'; |
| | | pack->diff_units = 'M'; |
| | | } |
| | | |
| | | void nmea_zero_GPGSA(nmeaGPGSA *pack) |
| | | { |
| | | memset(pack, 0, sizeof(nmeaGPGSA)); |
| | | pack->fix_mode = 'A'; |
| | | pack->fix_type = NMEA_FIX_BAD; |
| | | } |
| | | |
| | | void nmea_zero_GPGSV(nmeaGPGSV *pack) |
| | | { |
| | | memset(pack, 0, sizeof(nmeaGPGSV)); |
| | | } |
| | | |
| | | void nmea_zero_GPRMC(nmeaGPRMC *pack) |
| | | { |
| | | memset(pack, 0, sizeof(nmeaGPRMC)); |
| | | nmea_time_now(&pack->utc); |
| | | pack->status = 'V'; |
| | | pack->ns = 'N'; |
| | | pack->ew = 'E'; |
| | | pack->declin_ew = 'E'; |
| | | } |
| | | |
| | | void nmea_zero_GPVTG(nmeaGPVTG *pack) |
| | | { |
| | | memset(pack, 0, sizeof(nmeaGPVTG)); |
| | | pack->dir_t = 'T'; |
| | | pack->dec_m = 'M'; |
| | | pack->spn_n = 'N'; |
| | | pack->spk_k = 'K'; |
| | | } |
| | | |
| | | void nmea_zero_INFO(nmeaINFO *info) |
| | | { |
| | | memset(info, 0, sizeof(nmeaINFO)); |
| | | nmea_time_now(&info->utc); |
| | | info->sig = NMEA_SIG_BAD; |
| | | info->fix = NMEA_FIX_BAD; |
| | | } |
| | | |
| | | void nmea_time_now(nmeaTIME *stm) |
| | | { |
| | | time_t lt; |
| | | struct tm *tt; |
| | | |
| | | time(<); |
| | | tt = gmtime(<); |
| | | |
| | | stm->year = tt->tm_year; |
| | | stm->mon = tt->tm_mon; |
| | | stm->day = tt->tm_mday; |
| | | stm->hour = tt->tm_hour; |
| | | stm->min = tt->tm_min; |
| | | stm->sec = tt->tm_sec; |
| | | stm->hsec = 0; |
| | | } |
| | | |
| | | /* buf sample: "$GPRMC,134325.000,A,3029.8871,N,11423.1932,E,0.26,258.74,210113,,,A*" */ |
| | | int nmea_parse_line(char *buf, int buf_sz, nmeaINFO *info) |
| | | { |
| | | int type; |
| | | void *pack; |
| | | |
| | | type = nmea_pack_type(buf+1, buf_sz); /* Skip '$' */ |
| | | switch (type) |
| | | { |
| | | case GPGGA: |
| | | if( !(pack = malloc(sizeof(nmeaGPGGA))) ) |
| | | { |
| | | goto mem_fail; |
| | | } |
| | | |
| | | if( nmea_parse_GPGGA(buf, buf_sz, (nmeaGPGGA *)pack) ) |
| | | { |
| | | nmea_GPGGA2info(pack, info); |
| | | } |
| | | free(pack); |
| | | break; |
| | | |
| | | case GPGSA: |
| | | if( !(pack = malloc(sizeof(nmeaGPGSA))) ) |
| | | { |
| | | goto mem_fail; |
| | | } |
| | | |
| | | if( nmea_parse_GPGSA(buf, buf_sz, (nmeaGPGSA *)pack) ) |
| | | { |
| | | nmea_GPGSA2info(pack, info); |
| | | } |
| | | free(pack); |
| | | break; |
| | | |
| | | case GPGSV: |
| | | if( !(pack = malloc(sizeof(nmeaGPGSV))) ) |
| | | { |
| | | goto mem_fail; |
| | | } |
| | | |
| | | if( nmea_parse_GPGSV(buf, buf_sz, (nmeaGPGSV *)pack) ) |
| | | { |
| | | nmea_GPGSV2info(pack, info); |
| | | } |
| | | free(pack); |
| | | break; |
| | | |
| | | case GPRMC: |
| | | if( !(pack = malloc(sizeof(nmeaGPRMC))) ) |
| | | { |
| | | goto mem_fail; |
| | | } |
| | | |
| | | if( nmea_parse_GPRMC(buf, buf_sz, (nmeaGPRMC *)pack) ) |
| | | { |
| | | nmea_GPRMC2info(pack, info); |
| | | } |
| | | free(pack); |
| | | break; |
| | | |
| | | case GPVTG: |
| | | if( !(pack = malloc(sizeof(nmeaGPVTG))) ) |
| | | { |
| | | goto mem_fail; |
| | | } |
| | | |
| | | if( nmea_parse_GPVTG(buf, buf_sz, (nmeaGPVTG *)pack) ) |
| | | { |
| | | nmea_GPVTG2info(pack, info); |
| | | } |
| | | free(pack); |
| | | break; |
| | | |
| | | default: |
| | | break; |
| | | } |
| | | |
| | | return 0; |
| | | |
| | | mem_fail: |
| | | log_err("Insufficient memory!\n"); |
| | | return -1; |
| | | } |
| | | |
| | | int nmea_parse(char *data, int len, nmeaINFO *info) |
| | | { |
| | | int line_len, nbytes; |
| | | char line[512]; |
| | | |
| | | while(len > 0) |
| | | { |
| | | memset(line, 0, sizeof(line)); |
| | | nbytes = nmea_get_item_line(data, len, line, &line_len); |
| | | |
| | | /* Not a integrated line */ |
| | | if( line_len< 0 ) |
| | | break; |
| | | |
| | | if( line_len > 0 ) |
| | | { |
| | | nmea_parse_line(line, line_len, info); |
| | | } |
| | | |
| | | data += nbytes; |
| | | len -= nbytes; |
| | | } |
| | | |
| | | return 0; |
| | | } |
New file |
| | |
| | | /* |
| | | * |
| | | * NMEA library |
| | | * URL: http://nmea.sourceforge.net |
| | | * Author: Tim (xtimor@gmail.com) |
| | | * Licence: http://www.gnu.org/licenses/lgpl.html |
| | | * $Id: sentence.h 17 2008-03-11 11:56:11Z xtimor $ |
| | | * |
| | | */ |
| | | |
| | | /*! \file */ |
| | | |
| | | #ifndef __NMEA_INFO_H__ |
| | | #define __NMEA_INFO_H__ |
| | | |
| | | #define NMEA_SIG_BAD (0) |
| | | #define NMEA_SIG_LOW (1) |
| | | #define NMEA_SIG_MID (2) |
| | | #define NMEA_SIG_HIGH (3) |
| | | |
| | | #define NMEA_FIX_BAD (1) |
| | | #define NMEA_FIX_2D (2) |
| | | #define NMEA_FIX_3D (3) |
| | | |
| | | #define NMEA_MAXSAT (12) |
| | | #define NMEA_SATINPACK (4) |
| | | #define NMEA_NSATPACKS (NMEA_MAXSAT / NMEA_SATINPACK) |
| | | |
| | | #define NMEA_DEF_LAT (5001.2621) |
| | | #define NMEA_DEF_LON (3613.0595) |
| | | |
| | | |
| | | |
| | | #ifdef __cplusplus |
| | | extern "C" { |
| | | #endif |
| | | |
| | | /** |
| | | * Date and time data |
| | | * @see nmea_time_now |
| | | */ |
| | | typedef struct _nmeaTIME |
| | | { |
| | | int year; /**< Years since 1900 */ |
| | | int mon; /**< Months since January - [0,11] */ |
| | | int day; /**< Day of the month - [1,31] */ |
| | | int hour; /**< Hours since midnight - [0,23] */ |
| | | int min; /**< Minutes after the hour - [0,59] */ |
| | | int sec; /**< Seconds after the minute - [0,59] */ |
| | | int hsec; /**< Hundredth part of second - [0,99] */ |
| | | |
| | | } nmeaTIME; |
| | | |
| | | |
| | | /** |
| | | * Position data in fractional degrees or radians |
| | | */ |
| | | typedef struct _nmeaPOS |
| | | { |
| | | double lat; /**< Latitude */ |
| | | double lon; /**< Longitude */ |
| | | |
| | | } nmeaPOS; |
| | | |
| | | /** |
| | | * Information about satellite |
| | | * @see nmeaSATINFO |
| | | * @see nmeaGPGSV |
| | | */ |
| | | typedef struct _nmeaSATELLITE |
| | | { |
| | | int id; /**< Satellite PRN number */ |
| | | int in_use; /**< Used in position fix */ |
| | | int elv; /**< Elevation in degrees, 90 maximum */ |
| | | int azimuth; /**< Azimuth, degrees from true north, 000 to 359 */ |
| | | int sig; /**< Signal, 00-99 dB */ |
| | | |
| | | } nmeaSATELLITE; |
| | | |
| | | /** |
| | | * Information about all satellites in view |
| | | * @see nmeaINFO |
| | | * @see nmeaGPGSV |
| | | */ |
| | | typedef struct _nmeaSATINFO |
| | | { |
| | | int inuse; /**< Number of satellites in use (not those in view) */ |
| | | int inview; /**< Total number of satellites in view */ |
| | | nmeaSATELLITE sat[NMEA_MAXSAT]; /**< Satellites information */ |
| | | |
| | | } nmeaSATINFO; |
| | | |
| | | /** |
| | | * Summary GPS information from all parsed packets, |
| | | * used also for generating NMEA stream |
| | | * @see nmea_parse |
| | | * @see nmea_GPGGA2info, nmea_...2info |
| | | */ |
| | | typedef struct _nmeaINFO |
| | | { |
| | | int smask; /**< Mask specifying types of packages from which data have been obtained */ |
| | | |
| | | nmeaTIME utc; /**< UTC of position */ |
| | | |
| | | int sig; /**< GPS quality indicator (0 = Invalid; 1 = Fix; 2 = Differential, 3 = Sensitive) */ |
| | | int fix; /**< Operating mode, used for navigation (1 = Fix not available; 2 = 2D; 3 = 3D) */ |
| | | |
| | | double PDOP; /**< Position Dilution Of Precision */ |
| | | double HDOP; /**< Horizontal Dilution Of Precision */ |
| | | double VDOP; /**< Vertical Dilution Of Precision */ |
| | | |
| | | double lat; /**< Latitude in NDEG - +/-[degree][min].[sec/60] */ |
| | | double lon; /**< Longitude in NDEG - +/-[degree][min].[sec/60] */ |
| | | double elv; /**< Antenna altitude above/below mean sea level (geoid) in meters */ |
| | | double speed; /**< Speed over the ground in kilometers/hour */ |
| | | double direction; /**< Track angle in degrees True */ |
| | | double declination; /**< Magnetic variation degrees (Easterly var. subtracts from true course) */ |
| | | |
| | | nmeaSATINFO satinfo; /**< Satellites information */ |
| | | |
| | | } nmeaINFO; |
| | | |
| | | |
| | | |
| | | /** |
| | | * NMEA packets type which parsed and generated by library |
| | | */ |
| | | enum nmeaPACKTYPE |
| | | { |
| | | GPNON = 0x0000, /**< Unknown packet type. */ |
| | | GPGGA = 0x0001, /**< GGA - Essential fix data which provide 3D location and accuracy data. */ |
| | | GPGSA = 0x0002, /**< GSA - GPS receiver operating mode, SVs used for navigation, and DOP values. */ |
| | | GPGSV = 0x0004, /**< GSV - Number of SVs in view, PRN numbers, elevation, azimuth & SNR values. */ |
| | | GPRMC = 0x0008, /**< RMC - Recommended Minimum Specific GPS/TRANSIT Data. */ |
| | | GPVTG = 0x0010 /**< VTG - Actual track made good and speed over ground. */ |
| | | }; |
| | | |
| | | /** |
| | | * GGA packet information structure (Global Positioning System Fix Data) |
| | | */ |
| | | typedef struct _nmeaGPGGA |
| | | { |
| | | nmeaTIME utc; /**< UTC of position (just time) */ |
| | | double lat; /**< Latitude in NDEG - [degree][min].[sec/60] */ |
| | | char ns; /**< [N]orth or [S]outh */ |
| | | double lon; /**< Longitude in NDEG - [degree][min].[sec/60] */ |
| | | char ew; /**< [E]ast or [W]est */ |
| | | int sig; /**< GPS quality indicator (0 = Invalid; 1 = Fix; 2 = Differential, 3 = Sensitive) */ |
| | | int satinuse; /**< Number of satellites in use (not those in view) */ |
| | | double HDOP; /**< Horizontal dilution of precision */ |
| | | double elv; /**< Antenna altitude above/below mean sea level (geoid) */ |
| | | char elv_units; /**< [M]eters (Antenna height unit) */ |
| | | double diff; /**< Geoidal separation (Diff. between WGS-84 earth ellipsoid and mean sea level. '-' = geoid is below WGS-84 ellipsoid) */ |
| | | char diff_units; /**< [M]eters (Units of geoidal separation) */ |
| | | double dgps_age; /**< Time in seconds since last DGPS update */ |
| | | int dgps_sid; /**< DGPS station ID number */ |
| | | |
| | | } nmeaGPGGA; |
| | | |
| | | /** |
| | | * GSA packet information structure (Satellite status) |
| | | */ |
| | | typedef struct _nmeaGPGSA |
| | | { |
| | | char fix_mode; /**< Mode (M = Manual, forced to operate in 2D or 3D; A = Automatic, 3D/2D) */ |
| | | int fix_type; /**< Type, used for navigation (1 = Fix not available; 2 = 2D; 3 = 3D) */ |
| | | int sat_prn[NMEA_MAXSAT]; /**< PRNs of satellites used in position fix (null for unused fields) */ |
| | | double PDOP; /**< Dilution of precision */ |
| | | double HDOP; /**< Horizontal dilution of precision */ |
| | | double VDOP; /**< Vertical dilution of precision */ |
| | | |
| | | } nmeaGPGSA; |
| | | |
| | | /** |
| | | * GSV packet information structure (Satellites in view) |
| | | */ |
| | | typedef struct _nmeaGPGSV |
| | | { |
| | | int pack_count; /**< Total number of messages of this type in this cycle */ |
| | | int pack_index; /**< Message number */ |
| | | int sat_count; /**< Total number of satellites in view */ |
| | | nmeaSATELLITE sat_data[NMEA_SATINPACK]; |
| | | |
| | | } nmeaGPGSV; |
| | | |
| | | /** |
| | | * RMC packet information structure (Recommended Minimum sentence C) |
| | | */ |
| | | typedef struct _nmeaGPRMC |
| | | { |
| | | nmeaTIME utc; /**< UTC of position */ |
| | | char status; /**< Status (A = active or V = void) */ |
| | | double lat; /**< Latitude in NDEG - [degree][min].[sec/60] */ |
| | | char ns; /**< [N]orth or [S]outh */ |
| | | double lon; /**< Longitude in NDEG - [degree][min].[sec/60] */ |
| | | char ew; /**< [E]ast or [W]est */ |
| | | double speed; /**< Speed over the ground in knots */ |
| | | double direction; /**< Track angle in degrees True */ |
| | | double declination; /**< Magnetic variation degrees (Easterly var. subtracts from true course) */ |
| | | char declin_ew; /**< [E]ast or [W]est */ |
| | | char mode; /**< Mode indicator of fix type (A = autonomous, D = differential, E = estimated, N = not valid, S = simulator) */ |
| | | |
| | | } nmeaGPRMC; |
| | | |
| | | /** |
| | | * VTG packet information structure (Track made good and ground speed) |
| | | */ |
| | | typedef struct _nmeaGPVTG |
| | | { |
| | | double dir; /**< True track made good (degrees) */ |
| | | char dir_t; /**< Fixed text 'T' indicates that track made good is relative to true north */ |
| | | double dec; /**< Magnetic track made good */ |
| | | char dec_m; /**< Fixed text 'M' */ |
| | | double spn; /**< Ground speed, knots */ |
| | | char spn_n; /**< Fixed text 'N' indicates that speed over ground is in knots */ |
| | | double spk; /**< Ground speed, kilometers per hour */ |
| | | char spk_k; /**< Fixed text 'K' indicates that speed over ground is in kilometers/hour */ |
| | | |
| | | } nmeaGPVTG; |
| | | |
| | | void nmea_zero_INFO(nmeaINFO *info); |
| | | void nmea_zero_GPGGA(nmeaGPGGA *pack); |
| | | void nmea_zero_GPGSA(nmeaGPGSA *pack); |
| | | void nmea_zero_GPGSV(nmeaGPGSV *pack); |
| | | void nmea_zero_GPRMC(nmeaGPRMC *pack); |
| | | void nmea_zero_GPVTG(nmeaGPVTG *pack); |
| | | void nmea_time_now(nmeaTIME *t); |
| | | int nmea_parse(char *buf, int len, nmeaINFO *info); |
| | | |
| | | #ifdef __cplusplus |
| | | } |
| | | #endif |
| | | |
| | | #endif /* __NMEA_INFO_H__ */ |
New file |
| | |
| | | /* |
| | | * |
| | | * NMEA library |
| | | * URL: http://nmea.sourceforge.net |
| | | * Author: Tim (xtimor@gmail.com) |
| | | * Licence: http://www.gnu.org/licenses/lgpl.html |
| | | * $Id: context.c 17 2008-03-11 11:56:11Z xtimor $ |
| | | * |
| | | */ |
| | | #include "nmea_parse.h" |
| | | #include "cp_logger.h" |
| | | |
| | | #include <assert.h> |
| | | #include <stdarg.h> |
| | | #include <stdlib.h> |
| | | #include <stdio.h> |
| | | #include <ctype.h> |
| | | #include <string.h> |
| | | #include <limits.h> |
| | | |
| | | #define NMEA_TOKS_COMPARE (1) |
| | | #define NMEA_TOKS_PERCENT (2) |
| | | #define NMEA_TOKS_WIDTH (3) |
| | | #define NMEA_TOKS_TYPE (4) |
| | | |
| | | /** |
| | | * \brief Convert string to number |
| | | */ |
| | | int nmea_atoi(const char *str, int str_sz, int radix) |
| | | { |
| | | char *tmp_ptr; |
| | | char buff[NMEA_CONVSTR_BUF]; |
| | | int res = 0; |
| | | |
| | | if(str_sz < NMEA_CONVSTR_BUF) |
| | | { |
| | | memcpy(&buff[0], str, str_sz); |
| | | buff[str_sz] = '\0'; |
| | | res = strtol(&buff[0], &tmp_ptr, radix); |
| | | } |
| | | |
| | | return res; |
| | | } |
| | | |
| | | /** |
| | | * \brief Convert string to fraction number |
| | | */ |
| | | double nmea_atof(const char *str, int str_sz) |
| | | { |
| | | char *tmp_ptr; |
| | | char buff[NMEA_CONVSTR_BUF]; |
| | | double res = 0; |
| | | |
| | | if(str_sz < NMEA_CONVSTR_BUF) |
| | | { |
| | | memcpy(&buff[0], str, str_sz); |
| | | buff[str_sz] = '\0'; |
| | | res = strtod(&buff[0], &tmp_ptr); |
| | | } |
| | | |
| | | return res; |
| | | } |
| | | |
| | | /** |
| | | * \brief Analyse string (specificate for NMEA sentences) |
| | | */ |
| | | int nmea_scanf(const char *buff, int buff_sz, const char *format, ...) |
| | | { |
| | | const char *beg_tok; |
| | | const char *end_buf = buff + buff_sz; |
| | | |
| | | va_list arg_ptr; |
| | | int tok_type = NMEA_TOKS_COMPARE; |
| | | int width = 0; |
| | | const char *beg_fmt = 0; |
| | | int snum = 0, unum = 0; |
| | | |
| | | int tok_count = 0; |
| | | void *parg_target; |
| | | |
| | | va_start(arg_ptr, format); |
| | | |
| | | for(; *format && buff < end_buf; ++format) |
| | | { |
| | | switch(tok_type) |
| | | { |
| | | case NMEA_TOKS_COMPARE: |
| | | if('%' == *format) |
| | | tok_type = NMEA_TOKS_PERCENT; |
| | | else if(*buff++ != *format) |
| | | goto fail; |
| | | break; |
| | | case NMEA_TOKS_PERCENT: |
| | | width = 0; |
| | | beg_fmt = format; |
| | | tok_type = NMEA_TOKS_WIDTH; |
| | | case NMEA_TOKS_WIDTH: |
| | | if(isdigit(*format)) |
| | | break; |
| | | { |
| | | tok_type = NMEA_TOKS_TYPE; |
| | | if(format > beg_fmt) |
| | | width = nmea_atoi(beg_fmt, (int)(format - beg_fmt), 10); |
| | | } |
| | | case NMEA_TOKS_TYPE: |
| | | beg_tok = buff; |
| | | |
| | | if(!width && ('c' == *format || 'C' == *format) && *buff != format[1]) |
| | | width = 1; |
| | | |
| | | if(width) |
| | | { |
| | | if(buff + width <= end_buf) |
| | | buff += width; |
| | | else |
| | | goto fail; |
| | | } |
| | | else |
| | | { |
| | | if(!format[1] || (0 == (buff = (char *)memchr(buff, format[1], end_buf - buff)))) |
| | | buff = end_buf; |
| | | } |
| | | |
| | | if(buff > end_buf) |
| | | goto fail; |
| | | |
| | | tok_type = NMEA_TOKS_COMPARE; |
| | | tok_count++; |
| | | |
| | | parg_target = 0; width = (int)(buff - beg_tok); |
| | | |
| | | switch(*format) |
| | | { |
| | | case 'c': |
| | | case 'C': |
| | | parg_target = (void *)va_arg(arg_ptr, char *); |
| | | if(width && 0 != (parg_target)) |
| | | *((char *)parg_target) = *beg_tok; |
| | | break; |
| | | case 's': |
| | | case 'S': |
| | | parg_target = (void *)va_arg(arg_ptr, char *); |
| | | if(width && 0 != (parg_target)) |
| | | { |
| | | memcpy(parg_target, beg_tok, width); |
| | | ((char *)parg_target)[width] = '\0'; |
| | | } |
| | | break; |
| | | case 'f': |
| | | case 'g': |
| | | case 'G': |
| | | case 'e': |
| | | case 'E': |
| | | parg_target = (void *)va_arg(arg_ptr, double *); |
| | | if(width && 0 != (parg_target)) |
| | | *((double *)parg_target) = nmea_atof(beg_tok, width); |
| | | break; |
| | | }; |
| | | |
| | | if(parg_target) |
| | | break; |
| | | if(0 == (parg_target = (void *)va_arg(arg_ptr, int *))) |
| | | break; |
| | | if(!width) |
| | | break; |
| | | |
| | | switch(*format) |
| | | { |
| | | case 'd': |
| | | case 'i': |
| | | snum = nmea_atoi(beg_tok, width, 10); |
| | | memcpy(parg_target, &snum, sizeof(int)); |
| | | break; |
| | | case 'u': |
| | | unum = nmea_atoi(beg_tok, width, 10); |
| | | memcpy(parg_target, &unum, sizeof(unsigned int)); |
| | | break; |
| | | case 'x': |
| | | case 'X': |
| | | unum = nmea_atoi(beg_tok, width, 16); |
| | | memcpy(parg_target, &unum, sizeof(unsigned int)); |
| | | break; |
| | | case 'o': |
| | | unum = nmea_atoi(beg_tok, width, 8); |
| | | memcpy(parg_target, &unum, sizeof(unsigned int)); |
| | | break; |
| | | default: |
| | | goto fail; |
| | | }; |
| | | |
| | | break; |
| | | }; |
| | | } |
| | | |
| | | fail: |
| | | |
| | | va_end(arg_ptr); |
| | | |
| | | return tok_count; |
| | | } |
| | | |
| | | int nmea_parse_time(const char *buff, int buff_sz, nmeaTIME *res) |
| | | { |
| | | int success = 0; |
| | | |
| | | switch(buff_sz) |
| | | { |
| | | case sizeof("hhmmss") - 1: |
| | | success = (3 == nmea_scanf(buff, buff_sz, |
| | | "%2d%2d%2d", &(res->hour), &(res->min), &(res->sec) |
| | | )); |
| | | break; |
| | | case sizeof("hhmmss.s") - 1: |
| | | case sizeof("hhmmss.ss") - 1: |
| | | case sizeof("hhmmss.sss") - 1: |
| | | success = (4 == nmea_scanf(buff, buff_sz, |
| | | "%2d%2d%2d.%d", &(res->hour), &(res->min), &(res->sec), &(res->hsec) |
| | | )); |
| | | break; |
| | | default: |
| | | log_err("Parse of time error (format error)!\n"); |
| | | success = 0; |
| | | break; |
| | | } |
| | | |
| | | return (success?0:-1); |
| | | } |
| | | |
| | | /** |
| | | * \brief Define packet type by header (nmeaPACKTYPE). |
| | | * @param buff a constant character pointer of packet buffer. |
| | | * @param buff_sz buffer size. |
| | | * @return The defined packet type |
| | | * @see nmeaPACKTYPE |
| | | */ |
| | | int nmea_pack_type(const char *buff, int buff_sz) |
| | | { |
| | | static const char *pheads[] = { |
| | | "GPGGA", |
| | | "GPGSA", |
| | | "GPGSV", |
| | | "GPRMC", |
| | | "GPVTG", |
| | | }; |
| | | |
| | | assert(buff); |
| | | |
| | | if(buff_sz < 5) |
| | | return GPNON; |
| | | else if(0 == memcmp(buff, pheads[0], 5)) |
| | | return GPGGA; |
| | | else if(0 == memcmp(buff, pheads[1], 5)) |
| | | return GPGSA; |
| | | else if(0 == memcmp(buff, pheads[2], 5)) |
| | | return GPGSV; |
| | | else if(0 == memcmp(buff, pheads[3], 5)) |
| | | return GPRMC; |
| | | else if(0 == memcmp(buff, pheads[4], 5)) |
| | | return GPVTG; |
| | | |
| | | return GPNON; |
| | | } |
| | | |
| | | /** |
| | | * \brief Get the first line in buffer and check control sum (CRC). |
| | | * @param buff a constant character pointer of packets buffer. |
| | | * @param buff_sz buffer size. |
| | | * @param line pointer output for a line in the packet |
| | | * @param line_len a integer pointer for return the line length (must be defined). |
| | | * @return already read bytes to a line end from buff. |
| | | */ |
| | | int nmea_get_item_line(const char *buff, int buff_sz, char *line, int *line_len) |
| | | { |
| | | static const int tail_sz = 3 /* *[CRC] */ + 2 /* \r\n */; |
| | | char *start, *star; |
| | | int nread = 0; |
| | | |
| | | *line_len = -1; |
| | | |
| | | /* Data sample: |
| | | * $GPGGA,081803.000,3029.9100,N,11423.2012,E,1,05,1.6,38.7,M,-13.7,M,,0000*4C |
| | | * $GPGSA,A,3,18,24,21,22,15,,,,,,,,3.1,1.6,2.7*3A |
| | | * $GPRMC,081803.000,A,3029.9100,N,11423.2012,E,1.14,126.38,210113,,,A*62 |
| | | */ |
| | | start = strchr(buff, '$'); |
| | | if(!start) |
| | | { |
| | | /* Can not find the line start flag '$', means can not find an integrated line */ |
| | | return buff_sz; |
| | | } |
| | | |
| | | star = strchr(start, '*'); |
| | | if(!star) |
| | | { |
| | | /* Can not find the line CRC start flag '*', means can not find an integrated line */ |
| | | return buff_sz; |
| | | } |
| | | |
| | | *line_len = star - start + 1; /* include '*' */ |
| | | strncpy(line, start, *line_len); |
| | | |
| | | nread = (star-buff) + tail_sz ; |
| | | |
| | | return nread>buff_sz ? buff_sz : nread; |
| | | } |
| | | |
| | | /** |
| | | * \brief Find tail of packet ("\r\n") in buffer and check control sum (CRC). |
| | | * @param buff a constant character pointer of packets buffer. |
| | | * @param buff_sz buffer size. |
| | | * @param res_crc a integer pointer for return CRC of packet (must be defined). |
| | | * @return Number of bytes to packet tail. |
| | | */ |
| | | int nmea_find_tail(const char *buff, int buff_sz, int *res_crc) |
| | | { |
| | | static const int tail_sz = 3 /* *[CRC] */ + 2 /* \r\n */; |
| | | |
| | | const char *end_buff = buff + buff_sz; |
| | | int nread = 0; |
| | | int crc = 0; |
| | | |
| | | assert(buff && res_crc); |
| | | |
| | | *res_crc = -1; |
| | | |
| | | for(;buff < end_buff; ++buff, ++nread) |
| | | { |
| | | if(('$' == *buff) && nread) |
| | | { |
| | | buff = 0; |
| | | break; |
| | | } |
| | | else if('*' == *buff) |
| | | { |
| | | if(buff + tail_sz <= end_buff && '\r' == buff[3] && '\n' == buff[4]) |
| | | { |
| | | *res_crc = nmea_atoi(buff + 1, 2, 16); |
| | | nread = buff_sz - (int)(end_buff - (buff + tail_sz)); |
| | | if(*res_crc != crc) |
| | | { |
| | | *res_crc = -1; |
| | | buff = 0; |
| | | } |
| | | } |
| | | |
| | | break; |
| | | } |
| | | else if(nread) |
| | | crc ^= (int)*buff; |
| | | } |
| | | |
| | | if(*res_crc < 0 && buff) |
| | | nread = 0; |
| | | |
| | | return nread; |
| | | } |
| | | |
| | | /** |
| | | * \brief Parse GGA packet from buffer. |
| | | * @param buff a constant character pointer of packet buffer. |
| | | * @param buff_sz buffer size. |
| | | * @param pack a pointer of packet which will filled by function. |
| | | * @return 1 (true) - if parsed successfully or 0 (false) - if fail. |
| | | */ |
| | | int nmea_parse_GPGGA(const char *buff, int buff_sz, nmeaGPGGA *pack) |
| | | { |
| | | char time_buff[NMEA_TIMEPARSE_BUF]; |
| | | |
| | | assert(buff && pack); |
| | | |
| | | memset(pack, 0, sizeof(nmeaGPGGA)); |
| | | |
| | | log_dbg("parse_GPGGA: %s\n", buff); |
| | | |
| | | if(14 != nmea_scanf(buff, buff_sz, |
| | | "$GPGGA,%s,%f,%C,%f,%C,%d,%d,%f,%f,%C,%f,%C,%f,%d*", |
| | | &(time_buff[0]), |
| | | &(pack->lat), &(pack->ns), &(pack->lon), &(pack->ew), |
| | | &(pack->sig), &(pack->satinuse), &(pack->HDOP), &(pack->elv), &(pack->elv_units), |
| | | &(pack->diff), &(pack->diff_units), &(pack->dgps_age), &(pack->dgps_sid))) |
| | | { |
| | | log_err("GPGGA parse error!\n"); |
| | | return 0; |
| | | } |
| | | |
| | | if(0 != nmea_parse_time(&time_buff[0], (int)strlen(&time_buff[0]), &(pack->utc))) |
| | | { |
| | | log_err("GPGGA time parse error!\n"); |
| | | return 0; |
| | | } |
| | | |
| | | return 1; |
| | | } |
| | | |
| | | /** |
| | | * \brief Parse GSA packet from buffer. |
| | | * @param buff a constant character pointer of packet buffer. |
| | | * @param buff_sz buffer size. |
| | | * @param pack a pointer of packet which will filled by function. |
| | | * @return 1 (true) - if parsed successfully or 0 (false) - if fail. |
| | | */ |
| | | int nmea_parse_GPGSA(const char *buff, int buff_sz, nmeaGPGSA *pack) |
| | | { |
| | | assert(buff && pack); |
| | | |
| | | memset(pack, 0, sizeof(nmeaGPGSA)); |
| | | |
| | | log_dbg("parse_GPGSA: %s\n", buff); |
| | | |
| | | if(17 != nmea_scanf(buff, buff_sz, |
| | | "$GPGSA,%C,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%f,%f,%f*", |
| | | &(pack->fix_mode), &(pack->fix_type), |
| | | &(pack->sat_prn[0]), &(pack->sat_prn[1]), &(pack->sat_prn[2]), &(pack->sat_prn[3]), &(pack->sat_prn[4]), &(pack->sat_prn[5]), |
| | | &(pack->sat_prn[6]), &(pack->sat_prn[7]), &(pack->sat_prn[8]), &(pack->sat_prn[9]), &(pack->sat_prn[10]), &(pack->sat_prn[11]), |
| | | &(pack->PDOP), &(pack->HDOP), &(pack->VDOP))) |
| | | { |
| | | log_err("GPGSA parse error!\n"); |
| | | return 0; |
| | | } |
| | | |
| | | return 1; |
| | | } |
| | | |
| | | /** |
| | | * \brief Parse GSV packet from buffer. |
| | | * @param buff a constant character pointer of packet buffer. |
| | | * @param buff_sz buffer size. |
| | | * @param pack a pointer of packet which will filled by function. |
| | | * @return 1 (true) - if parsed successfully or 0 (false) - if fail. |
| | | */ |
| | | int nmea_parse_GPGSV(const char *buff, int buff_sz, nmeaGPGSV *pack) |
| | | { |
| | | int nsen, nsat; |
| | | |
| | | assert(buff && pack); |
| | | |
| | | memset(pack, 0, sizeof(nmeaGPGSV)); |
| | | |
| | | log_dbg("parse_GPGSV: %s\n", buff); |
| | | |
| | | nsen = nmea_scanf(buff, buff_sz, |
| | | "$GPGSV,%d,%d,%d," |
| | | "%d,%d,%d,%d," |
| | | "%d,%d,%d,%d," |
| | | "%d,%d,%d,%d," |
| | | "%d,%d,%d,%d*", |
| | | &(pack->pack_count), &(pack->pack_index), &(pack->sat_count), |
| | | &(pack->sat_data[0].id), &(pack->sat_data[0].elv), &(pack->sat_data[0].azimuth), &(pack->sat_data[0].sig), |
| | | &(pack->sat_data[1].id), &(pack->sat_data[1].elv), &(pack->sat_data[1].azimuth), &(pack->sat_data[1].sig), |
| | | &(pack->sat_data[2].id), &(pack->sat_data[2].elv), &(pack->sat_data[2].azimuth), &(pack->sat_data[2].sig), |
| | | &(pack->sat_data[3].id), &(pack->sat_data[3].elv), &(pack->sat_data[3].azimuth), &(pack->sat_data[3].sig)); |
| | | |
| | | nsat = (pack->pack_index - 1) * NMEA_SATINPACK; |
| | | nsat = (nsat + NMEA_SATINPACK > pack->sat_count)?pack->sat_count - nsat:NMEA_SATINPACK; |
| | | nsat = nsat * 4 + 3 /* first three sentence`s */; |
| | | |
| | | if(nsen < nsat || nsen > (NMEA_SATINPACK * 4 + 3)) |
| | | { |
| | | log_err("GPGSV parse error!\n"); |
| | | return 0; |
| | | } |
| | | |
| | | return 1; |
| | | } |
| | | |
| | | /** |
| | | * \brief Parse RMC packet from buffer. |
| | | * @param buff a constant character pointer of packet buffer. |
| | | * @param buff_sz buffer size. |
| | | * @param pack a pointer of packet which will filled by function. |
| | | * @return 1 (true) - if parsed successfully or 0 (false) - if fail. |
| | | */ |
| | | int nmea_parse_GPRMC(const char *buff, int buff_sz, nmeaGPRMC *pack) |
| | | { |
| | | int nsen; |
| | | char time_buff[NMEA_TIMEPARSE_BUF]; |
| | | |
| | | assert(buff && pack); |
| | | |
| | | memset(pack, 0, sizeof(nmeaGPRMC)); |
| | | |
| | | log_dbg("parse_GPGRMC: %s\n", buff); |
| | | |
| | | nsen = nmea_scanf(buff, buff_sz, |
| | | "$GPRMC,%s,%C,%f,%C,%f,%C,%f,%f,%2d%2d%2d,%f,%C,%C*", |
| | | &(time_buff[0]), |
| | | &(pack->status), &(pack->lat), &(pack->ns), &(pack->lon), &(pack->ew), |
| | | &(pack->speed), &(pack->direction), |
| | | &(pack->utc.day), &(pack->utc.mon), &(pack->utc.year), |
| | | &(pack->declination), &(pack->declin_ew), &(pack->mode)); |
| | | |
| | | if(nsen != 13 && nsen != 14) |
| | | { |
| | | log_err("GPRMC parse error!\n"); |
| | | return 0; |
| | | } |
| | | |
| | | if(0 != nmea_parse_time(&time_buff[0], (int)strlen(&time_buff[0]), &(pack->utc))) |
| | | { |
| | | log_err("GPRMC time parse error!\n"); |
| | | return 0; |
| | | } |
| | | |
| | | if(pack->utc.year < 90) |
| | | pack->utc.year += 100; |
| | | pack->utc.mon -= 1; |
| | | |
| | | return 1; |
| | | } |
| | | |
| | | /** |
| | | * \brief Parse VTG packet from buffer. |
| | | * @param buff a constant character pointer of packet buffer. |
| | | * @param buff_sz buffer size. |
| | | * @param pack a pointer of packet which will filled by function. |
| | | * @return 1 (true) - if parsed successfully or 0 (false) - if fail. |
| | | */ |
| | | int nmea_parse_GPVTG(const char *buff, int buff_sz, nmeaGPVTG *pack) |
| | | { |
| | | assert(buff && pack); |
| | | |
| | | memset(pack, 0, sizeof(nmeaGPVTG)); |
| | | |
| | | log_dbg("parse_GPVTG: %s\n", buff); |
| | | |
| | | if(8 != nmea_scanf(buff, buff_sz, |
| | | "$GPVTG,%f,%C,%f,%C,%f,%C,%f,%C*", |
| | | &(pack->dir), &(pack->dir_t), |
| | | &(pack->dec), &(pack->dec_m), |
| | | &(pack->spn), &(pack->spn_n), |
| | | &(pack->spk), &(pack->spk_k))) |
| | | { |
| | | log_err("GPVTG parse error!\n"); |
| | | return 0; |
| | | } |
| | | |
| | | if( pack->dir_t != 'T' || |
| | | pack->dec_m != 'M' || |
| | | pack->spn_n != 'N' || |
| | | pack->spk_k != 'K') |
| | | { |
| | | log_err("GPVTG parse error (format error)!\n"); |
| | | return 0; |
| | | } |
| | | |
| | | return 1; |
| | | } |
| | | |
| | | /** |
| | | * \brief Fill nmeaINFO structure by GGA packet data. |
| | | * @param pack a pointer of packet structure. |
| | | * @param info a pointer of summary information structure. |
| | | */ |
| | | void nmea_GPGGA2info(nmeaGPGGA *pack, nmeaINFO *info) |
| | | { |
| | | assert(pack && info); |
| | | |
| | | info->utc.hour = pack->utc.hour; |
| | | info->utc.min = pack->utc.min; |
| | | info->utc.sec = pack->utc.sec; |
| | | info->utc.hsec = pack->utc.hsec; |
| | | info->sig = pack->sig; |
| | | info->HDOP = pack->HDOP; |
| | | info->elv = pack->elv; |
| | | info->lat = ((pack->ns == 'N')?pack->lat:-(pack->lat)); |
| | | info->lon = ((pack->ew == 'E')?pack->lon:-(pack->lon)); |
| | | info->smask |= GPGGA; |
| | | } |
| | | |
| | | /** |
| | | * \brief Fill nmeaINFO structure by GSA packet data. |
| | | * @param pack a pointer of packet structure. |
| | | * @param info a pointer of summary information structure. |
| | | */ |
| | | void nmea_GPGSA2info(nmeaGPGSA *pack, nmeaINFO *info) |
| | | { |
| | | int i, j, nuse = 0; |
| | | |
| | | assert(pack && info); |
| | | |
| | | info->fix = pack->fix_type; |
| | | info->PDOP = pack->PDOP; |
| | | info->HDOP = pack->HDOP; |
| | | info->VDOP = pack->VDOP; |
| | | |
| | | for(i = 0; i < NMEA_MAXSAT; ++i) |
| | | { |
| | | for(j = 0; j < info->satinfo.inview; ++j) |
| | | { |
| | | if(pack->sat_prn[i] && pack->sat_prn[i] == info->satinfo.sat[j].id) |
| | | { |
| | | info->satinfo.sat[j].in_use = 1; |
| | | nuse++; |
| | | } |
| | | } |
| | | } |
| | | |
| | | info->satinfo.inuse = nuse; |
| | | info->smask |= GPGSA; |
| | | } |
| | | |
| | | /** |
| | | * \brief Fill nmeaINFO structure by GSV packet data. |
| | | * @param pack a pointer of packet structure. |
| | | * @param info a pointer of summary information structure. |
| | | */ |
| | | void nmea_GPGSV2info(nmeaGPGSV *pack, nmeaINFO *info) |
| | | { |
| | | int isat, isi, nsat; |
| | | |
| | | assert(pack && info); |
| | | |
| | | if(pack->pack_index > pack->pack_count || |
| | | pack->pack_index * NMEA_SATINPACK > NMEA_MAXSAT) |
| | | return; |
| | | |
| | | if(pack->pack_index < 1) |
| | | pack->pack_index = 1; |
| | | |
| | | info->satinfo.inview = pack->sat_count; |
| | | |
| | | nsat = (pack->pack_index - 1) * NMEA_SATINPACK; |
| | | nsat = (nsat + NMEA_SATINPACK > pack->sat_count)?pack->sat_count - nsat:NMEA_SATINPACK; |
| | | |
| | | for(isat = 0; isat < nsat; ++isat) |
| | | { |
| | | isi = (pack->pack_index - 1) * NMEA_SATINPACK + isat; |
| | | info->satinfo.sat[isi].id = pack->sat_data[isat].id; |
| | | info->satinfo.sat[isi].elv = pack->sat_data[isat].elv; |
| | | info->satinfo.sat[isi].azimuth = pack->sat_data[isat].azimuth; |
| | | info->satinfo.sat[isi].sig = pack->sat_data[isat].sig; |
| | | } |
| | | |
| | | info->smask |= GPGSV; |
| | | } |
| | | |
| | | /** |
| | | * \brief Fill nmeaINFO structure by RMC packet data. |
| | | * @param pack a pointer of packet structure. |
| | | * @param info a pointer of summary information structure. |
| | | */ |
| | | void nmea_GPRMC2info(nmeaGPRMC *pack, nmeaINFO *info) |
| | | { |
| | | assert(pack && info); |
| | | |
| | | if('A' == pack->status) |
| | | { |
| | | if(NMEA_SIG_BAD == info->sig) |
| | | info->sig = NMEA_SIG_MID; |
| | | if(NMEA_FIX_BAD == info->fix) |
| | | info->fix = NMEA_FIX_2D; |
| | | } |
| | | else if('V' == pack->status) |
| | | { |
| | | info->sig = NMEA_SIG_BAD; |
| | | info->fix = NMEA_FIX_BAD; |
| | | } |
| | | |
| | | info->utc = pack->utc; |
| | | info->lat = ((pack->ns == 'N')?pack->lat:-(pack->lat)); |
| | | info->lon = ((pack->ew == 'E')?pack->lon:-(pack->lon)); |
| | | info->speed = pack->speed * NMEA_TUD_KNOTS; |
| | | info->direction = pack->direction; |
| | | info->smask |= GPRMC; |
| | | } |
| | | |
| | | /** |
| | | * \brief Fill nmeaINFO structure by VTG packet data. |
| | | * @param pack a pointer of packet structure. |
| | | * @param info a pointer of summary information structure. |
| | | */ |
| | | void nmea_GPVTG2info(nmeaGPVTG *pack, nmeaINFO *info) |
| | | { |
| | | assert(pack && info); |
| | | |
| | | info->direction = pack->dir; |
| | | info->declination = pack->dec; |
| | | info->speed = pack->spk; |
| | | info->smask |= GPVTG; |
| | | } |
| | | |
program/fwed/gpsd/nmea_parse.h
program/fwed/gsmd/gsmd.c
program/fwed/gsmd/gsmd.h
program/fwed/gsmd/makefile
program/fwed/makefile
program/fwed/zigd/makefile
program/fwed/zigd/zigd.c
program/fwed/zigd/zigd.h
program/serial2socket/thread_mode/cp_comport.c
program/serial2socket/thread_mode/cp_comport.h
program/serial2socket/thread_mode/cp_logger.c
program/serial2socket/thread_mode/cp_logger.h
program/serial2socket/thread_mode/cp_proc.c
program/serial2socket/thread_mode/cp_proc.h
program/serial2socket/thread_mode/cp_socket.c
program/serial2socket/thread_mode/cp_socket.h
program/serial2socket/thread_mode/makefile
program/serial2socket/thread_mode/sp2sck.c
program/serial2socket/thread_mode/sp2sck.h
program/sqlite/build.sh
program/sqlite/makefile
program/sqlite/test_sqlite.c
program/unp/makefile
program/unp/socket_client.c
program/unp/socket_server_select.c
program/unp/socket_server_thread.c
program/unp/test.sh |