static void swift_init_stuff(struct stuff *ps) { ASTOBJ_INIT(ps); ps->generating_done = 0; ps->q = malloc(cfg_buffer_size); ps->pq_r = ps->q; ps->pq_w = ps->q; ps->qc = 0; ps->immediate_exit = 0; }
/*! * \internal * \brief Load and reload SMDI configuration. * \param reload this should be 1 if we are reloading and 0 if not. * * This function loads/reloads the SMDI configuration and starts and stops * interfaces accordingly. * * \return zero on success, -1 on failure, and 1 if no smdi interfaces were started. */ static int smdi_load(int reload) { struct ast_config *conf; struct ast_variable *v; struct ast_smdi_interface *iface = NULL; int res = 0; /* Config options */ speed_t baud_rate = B9600; /* 9600 baud rate */ tcflag_t paritybit = PARENB; /* even parity checking */ tcflag_t charsize = CS7; /* seven bit characters */ int stopbits = 0; /* One stop bit */ int msdstrip = 0; /* strip zero digits */ long msg_expiry = SMDI_MSG_EXPIRY_TIME; conf = ast_config_load(config_file); if (!conf) { if (reload) ast_log(LOG_NOTICE, "Unable to reload config %s: SMDI untouched\n", config_file); else ast_log(LOG_NOTICE, "Unable to load config %s: SMDI disabled\n", config_file); return 1; } /* Mark all interfaces that we are listening on. We will unmark them * as we find them in the config file, this way we know any interfaces * still marked after we have finished parsing the config file should * be stopped. */ if (reload) ASTOBJ_CONTAINER_MARKALL(&smdi_ifaces); for (v = ast_variable_browse(conf, "interfaces"); v; v = v->next) { if (!strcasecmp(v->name, "baudrate")) { if (!strcasecmp(v->value, "9600")) baud_rate = B9600; else if(!strcasecmp(v->value, "4800")) baud_rate = B4800; else if(!strcasecmp(v->value, "2400")) baud_rate = B2400; else if(!strcasecmp(v->value, "1200")) baud_rate = B1200; else { ast_log(LOG_NOTICE, "Invalid baud rate '%s' specified in %s (line %d), using default\n", v->value, config_file, v->lineno); baud_rate = B9600; } } else if (!strcasecmp(v->name, "msdstrip")) { if (!sscanf(v->value, "%d", &msdstrip)) { ast_log(LOG_NOTICE, "Invalid msdstrip value in %s (line %d), using default\n", config_file, v->lineno); msdstrip = 0; } else if (0 > msdstrip || msdstrip > 9) { ast_log(LOG_NOTICE, "Invalid msdstrip value in %s (line %d), using default\n", config_file, v->lineno); msdstrip = 0; } } else if (!strcasecmp(v->name, "msgexpirytime")) { if (!sscanf(v->value, "%ld", &msg_expiry)) { ast_log(LOG_NOTICE, "Invalid msgexpirytime value in %s (line %d), using default\n", config_file, v->lineno); msg_expiry = SMDI_MSG_EXPIRY_TIME; } } else if (!strcasecmp(v->name, "paritybit")) { if (!strcasecmp(v->value, "even")) paritybit = PARENB; else if (!strcasecmp(v->value, "odd")) paritybit = PARENB | PARODD; else if (!strcasecmp(v->value, "none")) paritybit = ~PARENB; else { ast_log(LOG_NOTICE, "Invalid parity bit setting in %s (line %d), using default\n", config_file, v->lineno); paritybit = PARENB; } } else if (!strcasecmp(v->name, "charsize")) { if (!strcasecmp(v->value, "7")) charsize = CS7; else if (!strcasecmp(v->value, "8")) charsize = CS8; else { ast_log(LOG_NOTICE, "Invalid character size setting in %s (line %d), using default\n", config_file, v->lineno); charsize = CS7; } } else if (!strcasecmp(v->name, "twostopbits")) { stopbits = ast_true(v->name); } else if (!strcasecmp(v->name, "smdiport")) { if (reload) { /* we are reloading, check if we are already * monitoring this interface, if we are we do * not want to start it again. This also has * the side effect of not updating different * setting for the serial port, but it should * be trivial to rewrite this section so that * options on the port are changed without * restarting the interface. Or the interface * could be restarted with out emptying the * queue. */ if ((iface = ASTOBJ_CONTAINER_FIND(&smdi_ifaces, v->value))) { ast_log(LOG_NOTICE, "SMDI interface %s already running, not restarting\n", iface->name); ASTOBJ_UNMARK(iface); ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); continue; } } if (!(iface = ast_calloc(1, sizeof(*iface)))) continue; ASTOBJ_INIT(iface); ASTOBJ_CONTAINER_INIT(&iface->md_q); ASTOBJ_CONTAINER_INIT(&iface->mwi_q); ast_copy_string(iface->name, v->value, sizeof(iface->name)); if (!(iface->file = fopen(iface->name, "r"))) { ast_log(LOG_ERROR, "Error opening SMDI interface %s (%s)\n", iface->name, strerror(errno)); ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); continue; } iface->fd = fileno(iface->file); /* Set the proper attributes for our serial port. */ /* get the current attributes from the port */ if (tcgetattr(iface->fd, &iface->mode)) { ast_log(LOG_ERROR, "Error getting atributes of %s (%s)\n", iface->name, strerror(errno)); ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); continue; } /* set the desired speed */ if (cfsetispeed(&iface->mode, baud_rate) || cfsetospeed(&iface->mode, baud_rate)) { ast_log(LOG_ERROR, "Error setting baud rate on %s (%s)\n", iface->name, strerror(errno)); ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); continue; } /* set the stop bits */ if (stopbits) iface->mode.c_cflag = iface->mode.c_cflag | CSTOPB; /* set two stop bits */ else iface->mode.c_cflag = iface->mode.c_cflag & ~CSTOPB; /* set one stop bit */ /* set the parity */ iface->mode.c_cflag = (iface->mode.c_cflag & ~PARENB & ~PARODD) | paritybit; /* set the character size */ iface->mode.c_cflag = (iface->mode.c_cflag & ~CSIZE) | charsize; /* commit the desired attributes */ if (tcsetattr(iface->fd, TCSAFLUSH, &iface->mode)) { ast_log(LOG_ERROR, "Error setting attributes on %s (%s)\n", iface->name, strerror(errno)); ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); continue; } /* set the msdstrip */ iface->msdstrip = msdstrip; /* set the message expiry time */ iface->msg_expiry = msg_expiry; /* start the listner thread */ if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Starting SMDI monitor thread for %s\n", iface->name); if (ast_pthread_create(&iface->thread, NULL, smdi_read, iface)) { ast_log(LOG_ERROR, "Error starting SMDI monitor thread for %s\n", iface->name); ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); continue; } ASTOBJ_CONTAINER_LINK(&smdi_ifaces, iface); ASTOBJ_UNREF(iface, ast_smdi_interface_destroy); ast_atomic_fetchadd_int(&me->usecnt, +1); } else { ast_log(LOG_NOTICE, "Ignoring unknown option %s in %s\n", v->name, config_file); } } ast_config_destroy(conf); /* Prune any interfaces we should no longer monitor. */ if (reload) ASTOBJ_CONTAINER_PRUNE_MARKED(&smdi_ifaces, ast_smdi_interface_destroy); ASTOBJ_CONTAINER_RDLOCK(&smdi_ifaces); /* TODO: this is bad, we need an ASTOBJ method for this! */ if (!smdi_ifaces.head) res = 1; ASTOBJ_CONTAINER_UNLOCK(&smdi_ifaces); return res; }
/*! \brief Read an SMDI message. * * \param iface_p the SMDI interface to read from. * * This function loops and reads from and SMDI interface. It must be stopped * using pthread_cancel(). */ static void *smdi_read(void *iface_p) { struct ast_smdi_interface *iface = iface_p; struct ast_smdi_md_message *md_msg; struct ast_smdi_mwi_message *mwi_msg; char c = '\0'; char *cp = NULL; int i; int start = 0; /* read an smdi message */ while ((c = fgetc(iface->file))) { /* check if this is the start of a message */ if (!start) { if (c == 'M') start = 1; } else { /* Determine if this is a MD or MWI message */ if(c == 'D') { /* MD message */ start = 0; if (!(md_msg = ast_calloc(1, sizeof(*md_msg)))) { ASTOBJ_UNREF(iface,ast_smdi_interface_destroy); return NULL; } ASTOBJ_INIT(md_msg); /* read the message desk number */ for(i = 0; i < SMDI_MESG_DESK_NUM_LEN; i++) md_msg->mesg_desk_num[i] = fgetc(iface->file); md_msg->mesg_desk_num[SMDI_MESG_DESK_NUM_LEN] = '\0'; /* read the message desk terminal number */ for(i = 0; i < SMDI_MESG_DESK_TERM_LEN; i++) md_msg->mesg_desk_term[i] = fgetc(iface->file); md_msg->mesg_desk_term[SMDI_MESG_DESK_TERM_LEN] = '\0'; /* read the message type */ md_msg->type = fgetc(iface->file); /* read the forwarding station number (may be blank) */ cp = &md_msg->fwd_st[0]; for (i = 0; i < SMDI_MAX_STATION_NUM_LEN + 1; i++) { if((c = fgetc(iface->file)) == ' ') { *cp = '\0'; break; } /* store c in md_msg->fwd_st */ if( i >= iface->msdstrip) *cp++ = c; } /* make sure the value is null terminated, even if this truncates it */ md_msg->fwd_st[SMDI_MAX_STATION_NUM_LEN] = '\0'; cp = NULL; /* read the calling station number (may be blank) */ cp = &md_msg->calling_st[0]; for (i = 0; i < SMDI_MAX_STATION_NUM_LEN + 1; i++) { if (!isdigit((c = fgetc(iface->file)))) { *cp = '\0'; break; } /* store c in md_msg->calling_st */ if (i >= iface->msdstrip) *cp++ = c; } /* make sure the value is null terminated, even if this truncates it */ md_msg->calling_st[SMDI_MAX_STATION_NUM_LEN] = '\0'; cp = NULL; /* add the message to the message queue */ md_msg->timestamp = ast_tvnow(); ast_smdi_md_message_push(iface, md_msg); ast_log(LOG_DEBUG, "Recieved SMDI MD message on %s\n", iface->name); ASTOBJ_UNREF(md_msg, ast_smdi_md_message_destroy); } else if(c == 'W') { /* MWI message */ start = 0; if (!(mwi_msg = ast_calloc(1, sizeof(*mwi_msg)))) { ASTOBJ_UNREF(iface,ast_smdi_interface_destroy); return NULL; } ASTOBJ_INIT(mwi_msg); /* discard the 'I' (from 'MWI') */ fgetc(iface->file); /* read the forwarding station number (may be blank) */ cp = &mwi_msg->fwd_st[0]; for (i = 0; i < SMDI_MAX_STATION_NUM_LEN + 1; i++) { if ((c = fgetc(iface->file)) == ' ') { *cp = '\0'; break; } /* store c in md_msg->fwd_st */ if (i >= iface->msdstrip) *cp++ = c; } /* make sure the station number is null terminated, even if this will truncate it */ mwi_msg->fwd_st[SMDI_MAX_STATION_NUM_LEN] = '\0'; cp = NULL; /* read the mwi failure cause */ for (i = 0; i < SMDI_MWI_FAIL_CAUSE_LEN; i++) mwi_msg->cause[i] = fgetc(iface->file); mwi_msg->cause[SMDI_MWI_FAIL_CAUSE_LEN] = '\0'; /* add the message to the message queue */ mwi_msg->timestamp = ast_tvnow(); ast_smdi_mwi_message_push(iface, mwi_msg); ast_log(LOG_DEBUG, "Recieved SMDI MWI message on %s\n", iface->name); ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy); } else { ast_log(LOG_ERROR, "Unknown SMDI message type recieved on %s (M%c).\n", iface->name, c); start = 0; } } } ast_log(LOG_ERROR, "Error reading from SMDI interface %s, stopping listener thread\n", iface->name); ASTOBJ_UNREF(iface,ast_smdi_interface_destroy); return NULL; }