⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smsc_emi_x25.c

📁 The Kannel Open Source WAP and SMS gateway works as both an SMS gateway, for implementing keyword b
💻 C
📖 第 1 页 / 共 3 页
字号:
    if (strstr(smsc->buffer, "NO CARRIER")) need_to_connect = 1;    if (strstr(smsc->buffer, "NO DIALTONE")) need_to_connect = 1;    /* Clear the buffer */    while (need_to_connect) {        /* Connect */        need_to_connect = emi_open_connection(smsc) < 0;        /* Clear the buffer so that the next call to guarantee           doesn't find the "NO CARRIER" string again. */        smsc->buflen = 0;        memset(smsc->buffer, 0, smsc->bufsize);    }    return 0;}static int at_dial(char *device, char *phonenum, char *at_prefix, time_t how_long){    char tmpbuff[1024];    int howmanyread = 0;    int thistime = 0;    int redial;    int fd = -1;    int ret;    time_t timestart;    struct termios tios;    /* The time at the start of the function is used when       determining whether we have used up our allotted       dial time and have to abort. */    time(&timestart);    /* Open the device properly. Remember to set the       access codes correctly. */    fd = open(device, O_RDWR | O_NONBLOCK | O_NOCTTY);    if (fd == -1) {        error(errno, "at_dial: error opening character device <%s>", device);        goto error;    }    tcflush(fd, TCIOFLUSH);    /* The speed initialisation is pretty important. */    tcgetattr(fd, &tios);    cfsetospeed(&tios, B115200);    cfsetispeed(&tios, B115200);    kannel_cfmakeraw(&tios);    tios.c_cflag |= (HUPCL | CREAD | CRTSCTS);    tcsetattr(fd, TCSANOW, &tios);    /* Dial using an AT command string. */    for (redial = 1; redial; ) {        info(0, "at_dial: dialing <%s> on <%s> for <%i> seconds",             phonenum, device,             (int)(how_long - (time(NULL) - timestart)));        /* Send AT dial request. */        howmanyread = 0;        sprintf(tmpbuff, "%s%s\r\n", at_prefix, phonenum);        ret = write(fd, tmpbuff, strlen(tmpbuff));  /* errors... -mg */        memset(&tmpbuff, 0, sizeof(tmpbuff));        /* Read the answer to the AT command and react accordingly. */        for (; ; ) {            /* We don't want to dial forever */            if (how_long != 0 && time(NULL) > timestart + how_long)                goto timeout;            /* We don't need more space for dialout */            if (howmanyread >= (int) sizeof(tmpbuff))                goto error;            /* We read 1 char a time so that we don't               accidentally read past the modem chat and               into the SMSC datastream -mg */            thistime = read(fd, &tmpbuff[howmanyread], 1);            if (thistime == -1) {                if (errno == EAGAIN) continue;                if (errno == EINTR) continue;                goto error;            } else {                howmanyread += thistime;            }            /* Search for the newline on the AT status line. */            if (tmpbuff[howmanyread - 1] == '\r'                || tmpbuff[howmanyread - 1] == '\n') {                /* XXX ADD ALL POSSIBLE CHAT STRINGS XXX */                if (strstr(tmpbuff, "CONNECT") != NULL) {                    debug("bb.sms.emi", 0, "at_dial: CONNECT");                    redial = 0;                    break;                } else if (strstr(tmpbuff, "NO CARRIER") != NULL) {                    debug("bb.sms.emi", 0, "at_dial: NO CARRIER");                    redial = 1;                    break;                } else if (strstr(tmpbuff, "BUSY") != NULL) {                    debug("bb.sms.emi", 0, "at_dial: BUSY");                    redial = 1;                    break;                } else if (strstr(tmpbuff, "NO DIALTONE") != NULL) {                    debug("bb.sms.emi", 0, "at_dial: NO DIALTONE");                    redial = 1;                    break;                }            } /* End of if lastchr=='\r'||'\n'. */            /* Thou shall not consume all system resources               by repeatedly looping a strstr search when               the string update latency is very high as it               is in serial communication. -mg */            usleep(1000);        } /* End of read loop. */        /* Thou shall not flood the modem with dial requests. -mg */        sleep(1);    } /* End of dial loop. */    debug("bb.sms.emi", 0, "at_dial: done with dialing");    return fd;timeout:    error(0, "at_dial timed out");    close(fd);    return -1;error:    error(0, "at_dial failed");    close(fd);    return -1;}/****************************************************************************** * Wait for an ACK or NACK from the remote * * REQUIRED by the protocol that it must be waited... */static int wait_for_ack(SMSCenter *smsc, int op_type){    char *tmpbuff;    int found = 0;    int n;    time_t start;    tmpbuff = gw_malloc(10 * 1024);    memset(tmpbuff, 0, 10*1024);    start = time(NULL);    do {        /* check for data */        n = get_data(smsc, tmpbuff, 1024 * 10);	/* At least the X.31 interface wants to append the data.	   Kalle, what about the TCP/IP interface? Am I correct	   that you are assuming that the message arrives in a 	   single read(2)? -mg */	if (n > 0)	    memorybuffer_append_data(smsc, tmpbuff, n);        /* act on data */        if (memorybuffer_has_rawmessage(smsc, op_type, 'R') > 0) {            memorybuffer_cut_rawmessage(smsc, tmpbuff, 10*1024);            debug("bb.sms.emi", 0, "Found ACK/NACK: <%s>", tmpbuff);            found = 1;        }    } while (!found && ((time(NULL) - start) < 5));    gw_free(tmpbuff);    return found;}/****************************************************************************** * Get the modem buffer data to buff, return the amount read * * Reads from main fd, but also from backup-fd - does accept if needed */static int get_data(SMSCenter *smsc, char *buff, int length){    int n = 0;    struct sockaddr_in client_addr;    socklen_t client_addr_len;    fd_set rf;    struct timeval to;    int ret;    memset(buff, 0, length);    if (smsc->type == SMSC_TYPE_EMI_X25) {        tcdrain(smsc->emi_fd);        n = read(smsc->emi_fd, buff, length);        return n;    }    FD_ZERO(&rf);    if (smsc->emi_fd >= 0) FD_SET(smsc->emi_fd, &rf);    if (smsc->emi_secondary_fd >= 0) FD_SET(smsc->emi_secondary_fd, &rf);    if (smsc->emi_backup_fd > 0) FD_SET(smsc->emi_backup_fd, &rf);    FD_SET(0, &rf);    to.tv_sec = 0;    to.tv_usec = 100;    ret = select(FD_SETSIZE, &rf, NULL, NULL, &to);    if (ret > 0) {        if (smsc->emi_secondary_fd >= 0 && FD_ISSET(smsc->emi_secondary_fd, &rf)) {            n = read(smsc->emi_secondary_fd, buff, length - 1);            if (n == -1) {                error(errno, "Error - Secondary socket closed");                close(smsc->emi_secondary_fd);                smsc->emi_secondary_fd = -1;            } else if (n == 0) {                info(0, "Secondary socket closed by SMSC");                close(smsc->emi_secondary_fd);                smsc->emi_secondary_fd = -1;            } else {			/* UGLY! We  put 'X' after message */                buff[n] = 'X'; 	/* if it is from secondary fd!!!  */                n++;            }        } else if (smsc->emi_fd >= 0 && FD_ISSET(smsc->emi_fd, &rf)) {            n = read(smsc->emi_fd, buff, length);            if (n == 0) {                close(smsc->emi_fd);                info(0, "Main EMI socket closed by SMSC");                smsc->emi_fd = -1; 	/* ready to be re-opened */            }        }        if ((smsc->emi_backup_fd > 0) && FD_ISSET(smsc->emi_backup_fd, &rf)) {            if (smsc->emi_secondary_fd == -1) {		Octstr *ip, *allow;		                smsc->emi_secondary_fd = accept(smsc->emi_backup_fd,			  (struct sockaddr *)&client_addr, &client_addr_len);		ip = host_ip(client_addr);		if (smsc->emi_backup_allow_ip == NULL)		    allow = NULL;		else		    allow = octstr_create(smsc->emi_backup_allow_ip);		if (is_allowed_ip(allow, octstr_imm("*.*.*.*"), ip) == 0) {		    info(0, "SMSC secondary connection tried from <%s>, "		    	    "disconnected",			    octstr_get_cstr(ip));		    octstr_destroy(ip);		    octstr_destroy(allow);		    close(smsc->emi_secondary_fd);		    smsc->emi_secondary_fd = -1;		    return 0;		}                info(0, "Secondary socket opened by SMSC from <%s>",		     octstr_get_cstr(ip));		octstr_destroy(ip);		octstr_destroy(allow);            } else                info(0, "New connection request while old secondary is open!");        }    }    if (n > 0) {        debug("bb.sms.emi", 0, "get_data:Read %d bytes: <%.*s>", n, n, buff);        debug("bb.sms.emi", 0, "get_data:smsc->buffer == <%s>", smsc->buffer);    }    return n;}/******************************************************************************* Put the buff data to the modem buffer, return the amount of data put*/static int put_data(SMSCenter *smsc, char *buff, int length, int is_backup){    size_t len = length;    int ret;    int fd = -1;    fd = smsc->emi_fd;    tcdrain(smsc->emi_fd);    /* Write until all data has been successfully written to the fd. */    while (len > 0) {        ret = write(fd, buff, len);        if (ret == -1) {            if (errno == EINTR) continue;            if (errno == EAGAIN) continue;            error(errno, "Writing to fd failed");            return -1;        }        /* ret may be less than len, if the writing           was interrupted by a signal. */        len -= ret;        buff += ret;    }    if (smsc->type == SMSC_TYPE_EMI_X25) {        /* Make sure the data gets written immediately.           Wait a while just to add some latency so           that the modem (or the UART) doesn't choke           on the data. */        tcdrain(smsc->emi_fd);        usleep(1000);    }    return 0;}/******************************************************************************* Append the buff data to smsc->buffer*/static int memorybuffer_append_data(SMSCenter *smsc, char *buff, int length){    while (smsc->bufsize < (smsc->buflen + length)) { /* buffer too small */        char *p = gw_realloc(smsc->buffer, smsc->bufsize * 2);        smsc->buffer = p;        smsc->bufsize *= 2;    }    memcpy(smsc->buffer + smsc->buflen, buff, length);    smsc->buflen += length;    return 0;}/******************************************************************************* Insert (put to head) the buff data to smsc->buffer*/static int memorybuffer_insert_data(SMSCenter *smsc, char *buff, int length){    while (smsc->bufsize < (smsc->buflen + length)) { /* buffer too small */        char *p = gw_realloc(smsc->buffer, smsc->bufsize * 2);        smsc->buffer = p;        smsc->bufsize *= 2;    }    memmove(smsc->buffer + length, smsc->buffer, smsc->buflen);    memcpy(smsc->buffer, buff, length);    smsc->buflen += length;    return 0;}/******************************************************************************* Check the smsc->buffer for a raw STX...ETX message*/static int memorybuffer_has_rawmessage(SMSCenter *smsc, int type, char auth){    char tmpbuff[1024], tmpbuff2[1024];    char *stx, *etx;    stx = memchr(smsc->buffer, '\2', smsc->buflen);    etx = memchr(smsc->buffer, '\3', smsc->buflen);    if (stx && etx && stx < etx) {        strncpy(tmpbuff, stx, etx - stx + 1);        tmpbuff[etx - stx + 1] = '\0';        if (auth)            sprintf(tmpbuff2, "/%c/%02i/", auth, type);        else            sprintf(tmpbuff2, "/%02i/", type);        if (strstr(tmpbuff, tmpbuff2) != NULL) {            debug("bb.sms.emi", 0, "found message <%c/%02i>...msg <%s>", auth, type, tmpbuff);            return 1;        }    }    return 0;}/******************************************************************************* Cut the first raw message from the smsc->buffer* and put it in buff, return success 0, failure -1*/static int memorybuffer_cut_rawmessage(SMSCenter *smsc, char *buff, int length){    char *stx, *etx;    int size_of_cut_piece;    int size_of_the_rest;    /* We don't check for NULLs since we're sure that nobody has fooled       around with smsc->buffer since has_rawmessage was last called... */    stx = memchr(smsc->buffer, '\2', smsc->buflen);    etx = memchr(smsc->buffer, '\3', smsc->buflen);    if (*(etx + 1) == 'X')	/* secondary! UGLY KLUDGE */        etx++;    size_of_cut_piece = (etx - stx) + 1;    size_of_the_rest = (smsc->buflen - size_of_cut_piece);    if (length < size_of_cut_piece) {        error(0, "the buffer you provided for cutting was too small");        return -1;    }    /* move the part before our magic rawmessage to the safe house */    memcpy(buff, stx, size_of_cut_piece);    buff[size_of_cut_piece] = '\0'; 	/* NULL-terminate */    /* move the stuff in membuffer one step down */    memmove(stx, etx + 1, (smsc->buffer + smsc->bufsize) - stx );    smsc->buflen -= size_of_cut_piece;    return 0;}/******************************************************************************* Parse the raw message to the Msg structure*/static int parse_rawmessage_to_msg(SMSCenter *smsc, Msg **msg,                                   char *rawmessage, int length){    char emivars[128][1024];    char *leftslash, *rightslash;    char isotext[2048];    int msgnbr;    int tmpint;    msgnbr = -1;    memset(isotext, 0, sizeof(isotext));    strncpy(isotext, rawmessage, length);    leftslash = isotext;    for (tmpint = 0; leftslash != NULL; tmpint++) {        rightslash = strchr(leftslash + 1, '/');        if (rightslash == NULL)            rightslash = strchr(leftslash + 1, '\3');        if (rightslash == NULL)            break;        *rightslash = '\0';        strcpy(emivars[tmpint], leftslash + 1);        leftslash = rightslash;    }    if (strcmp(emivars[3], "01") == 0) {

⌨️ 快捷键说明

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