📄 smsc_emi_x25.c
字号:
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(×tart); /* 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 + -