usock.c.svn-base
来自「Linux下gsm/gprs modem的看守程序。支持短信发送与接受。」· SVN-BASE 代码 · 共 1,745 行 · 第 1/4 页
SVN-BASE
1,745 行
* <CR><LF>+CPBR: <index2>,<unmber>,<type>,<text>]] */ gp.index = er->tokens[0].u.numeric; strlcpy(gp.numb, er->tokens[1].u.string, GSMD_PB_NUMB_MAXLEN+1); gp.type = er->tokens[2].u.numeric; strlcpy(gp.text, er->tokens[3].u.string, GSMD_PB_TEXT_MAXLEN+1); } else { DEBUGP("Invalid Input : Parse error\n"); return -EINVAL; } talloc_free(er); return gsmd_ucmd_submit(gu, GSMD_MSG_PHONEBOOK, GSMD_PHONEBOOK_READ, cmd->id, sizeof(gp), &gp);}static int phonebook_readrg_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp){ struct gsmd_user *gu = ctx; struct gsmd_phonebooks gps; struct gsm_extrsp *er; DEBUGP("resp: %s\n", resp); er = extrsp_parse(cmd, resp); if ( !er ) return -ENOMEM; gps.is_last = (cmd->ret == 0 || cmd->ret == 4)? 1:0; if ( !strncmp(resp, "OK", 2) ) { /* The record is empty or could not read yet */ gps.pb.index = 0; } else if ( !strncmp(resp, "+CME", 4) ) { DEBUGP("+CME error\n"); /* +CME ERROR: 21 */ gps.pb.index = 0 - atoi(strpbrk(resp, "0123456789")); } else if ( er->num_tokens == 4 && er->tokens[0].type == GSMD_ECMD_RTT_NUMERIC && er->tokens[1].type == GSMD_ECMD_RTT_STRING && er->tokens[2].type == GSMD_ECMD_RTT_NUMERIC && er->tokens[3].type == GSMD_ECMD_RTT_STRING ) { /* * [+CPBR: <index1>,<number>,<type>,<text>[[...] * <CR><LF>+CPBR: <index2>,<unmber>,<type>,<text>]] */ gps.pb.index = er->tokens[0].u.numeric; strlcpy(gps.pb.numb, er->tokens[1].u.string, GSMD_PB_NUMB_MAXLEN+1); gps.pb.type = er->tokens[2].u.numeric; strlcpy(gps.pb.text, er->tokens[3].u.string, GSMD_PB_TEXT_MAXLEN+1); } else { DEBUGP("Invalid Input : Parse error\n"); return -EINVAL; } talloc_free(er); return gsmd_ucmd_submit(gu, GSMD_MSG_PHONEBOOK, GSMD_PHONEBOOK_READRG, cmd->id, sizeof(gps), &gps);}static int phonebook_write_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp){ DEBUGP("resp: %s\n", resp); return gsmd_ucmd_submit(ctx, GSMD_MSG_PHONEBOOK, GSMD_PHONEBOOK_WRITE, cmd->id, strlen(resp) + 1, resp);}static int phonebook_delete_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp){ DEBUGP("resp: %s\n", resp); return gsmd_ucmd_submit(ctx, GSMD_MSG_PHONEBOOK, GSMD_PHONEBOOK_DELETE, cmd->id, strlen(resp) + 1, resp);}static int phonebook_get_support_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp){ /* TODO: Need to handle command error */ /* +CPBR: (1-100),44,16 */ struct gsmd_user *gu = ctx; struct gsmd_phonebook_support gps; char *fcomma, *lcomma; char *dash; DEBUGP("resp: %s\n", resp); dash = strchr(resp, '-'); if (!dash) return -EIO; /* TODO: Send a response */ gps.index = atoi(dash + 1); fcomma = strchr(resp, ','); if (!fcomma) return -EIO; /* TODO: Send a response */ gps.nlength = atoi(fcomma+1); lcomma = strrchr(resp, ','); if (!lcomma) return -EIO; /* TODO: Send a response */ gps.tlength = atoi(lcomma+1); return gsmd_ucmd_submit(gu, GSMD_MSG_PHONEBOOK, GSMD_PHONEBOOK_GET_SUPPORT, cmd->id, sizeof(gps), &gps);}static int phonebook_list_storage_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp){ /* TODO; using link list ; need to handle command error */ struct gsmd_user *gu = ctx; struct gsmd_phonebook_storage gps; char *ptr; DEBUGP("resp: %s\n", resp); /* * +CPBS: (<storage>s) */ gps.num = 0; if (!strncmp(resp, "+CPBS", 5)) { char* delim = "(,"; ptr = strpbrk(resp, delim); while (ptr) { strncpy(gps.mem[gps.num].type, ptr + 2, 2); gps.mem[gps.num].type[2] = '\0'; ptr = strpbrk(ptr + 2, delim); gps.num++; } } return gsmd_ucmd_submit(gu, GSMD_MSG_PHONEBOOK, GSMD_PHONEBOOK_LIST_STORAGE, cmd->id, sizeof(gps), &gps);}static int usock_rcv_phonebook(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,int len){ struct gsmd_atcmd *cmd = NULL; struct gsmd_phonebook_readrg *gpr; struct gsmd_phonebook *gp; struct gsmd_phonebook_find *gpf; int *index; int atcmd_len; char *storage; char buf[1024]; switch (gph->msg_subtype) { case GSMD_PHONEBOOK_LIST_STORAGE: cmd = atcmd_fill("AT+CPBS=?", 9 + 1, &phonebook_list_storage_cb, gu, gph->id, NULL); break; case GSMD_PHONEBOOK_SET_STORAGE: if (len < sizeof(*gph) + 3) return -EINVAL; storage = (char*) ((void *)gph + sizeof(*gph)); /* ex. AT+CPBS="ME" */ atcmd_len = 1 + strlen("AT+CPBS=\"") + 2 + strlen("\""); cmd = atcmd_fill("AT+CPBS=\"", atcmd_len, &usock_cmd_cb, gu, gph->id, NULL); if (!cmd) return -ENOMEM; sprintf(cmd->buf, "AT+CPBS=\"%s\"", storage); break; case GSMD_PHONEBOOK_FIND: if(len < sizeof(*gph) + sizeof(*gpf)) return -EINVAL; gpf = (struct gsmd_phonebook_find *) ((void *)gph + sizeof(*gph)); atcmd_len = 1 + strlen("AT+CPBF=\"") + strlen(gpf->findtext) + strlen("\""); cmd = atcmd_fill("AT+CPBF=\"", atcmd_len, &phonebook_find_cb, gu, gph->id, NULL); if (!cmd) return -ENOMEM; sprintf(cmd->buf, "AT+CPBF=\"%s\"", gpf->findtext); break; case GSMD_PHONEBOOK_READ: if(len < sizeof(*gph) + sizeof(int)) return -EINVAL; index = (int *) ((void *)gph + sizeof(*gph)); sprintf(buf, "%d", *index); /* ex, AT+CPBR=23 */ atcmd_len = 1 + strlen("AT+CPBR=") + strlen(buf); cmd = atcmd_fill("AT+CPBR=", atcmd_len, &phonebook_read_cb, gu, gph->id, NULL); if (!cmd) return -ENOMEM; sprintf(cmd->buf, "AT+CPBR=%d", *index); break; case GSMD_PHONEBOOK_READRG: if(len < sizeof(*gph) + sizeof(*gpr)) return -EINVAL; gpr = (struct gsmd_phonebook_readrg *) ((void *)gph + sizeof(*gph)); sprintf(buf, "%d,%d", gpr->index1, gpr->index2); /* ex, AT+CPBR=1,100 */ atcmd_len = 1 + strlen("AT+CPBR=") + strlen(buf); cmd = atcmd_fill("AT+CPBR=", atcmd_len, &phonebook_readrg_cb, gu, gph->id, NULL); if (!cmd) return -ENOMEM; sprintf(cmd->buf, "AT+CPBR=%s", buf); break; case GSMD_PHONEBOOK_WRITE: if(len < sizeof(*gph) + sizeof(*gp)) return -EINVAL; gp = (struct gsmd_phonebook *) ((void *)gph + sizeof(*gph)); sprintf(buf, "%d,\"%s\",%d,\"%s\"", gp->index, gp->numb, gp->type, gp->text); atcmd_len = 1 + strlen("AT+CPBW=") + strlen(buf); cmd = atcmd_fill("AT+CPBW=", atcmd_len, &phonebook_write_cb, gu, gph->id, NULL); if (!cmd) return -ENOMEM; sprintf(cmd->buf, "AT+CPBW=%s", buf); break; case GSMD_PHONEBOOK_DELETE: if(len < sizeof(*gph) + sizeof(int)) return -EINVAL; index = (int *) ((void *)gph + sizeof(*gph)); sprintf(buf, "%d", *index); /* ex, AT+CPBW=3*/ atcmd_len = 1 + strlen("AT+CPBW=") + strlen(buf); cmd = atcmd_fill("AT+CPBW=", atcmd_len, &phonebook_delete_cb, gu, gph->id, NULL); if (!cmd) return -ENOMEM; sprintf(cmd->buf, "AT+CPBW=%s", buf); break; case GSMD_PHONEBOOK_GET_SUPPORT: cmd = atcmd_fill("AT+CPBR=?", 9+1, &phonebook_get_support_cb, gu, gph->id, NULL); break; default: return -EINVAL; } if (cmd) return atcmd_submit(gu->gsmd, cmd); else return 0;}static usock_msg_handler *pcmd_type_handlers[__NUM_GSMD_MSGS] = { [GSMD_MSG_PASSTHROUGH] = &usock_rcv_passthrough, [GSMD_MSG_EVENT] = &usock_rcv_event, [GSMD_MSG_VOICECALL] = &usock_rcv_voicecall, [GSMD_MSG_PIN] = &usock_rcv_pin, [GSMD_MSG_PHONE] = &usock_rcv_phone, [GSMD_MSG_NETWORK] = &usock_rcv_network, [GSMD_MSG_SMS] = &usock_rcv_sms, [GSMD_MSG_CB] = &usock_rcv_cb, [GSMD_MSG_PHONEBOOK] = &usock_rcv_phonebook, [GSMD_MSG_MODEM] = &usock_rcv_modem,};static int usock_rcv_pcmd(struct gsmd_user *gu, char *buf, int len){ struct gsmd_msg_hdr *gph = (struct gsmd_msg_hdr *)buf; usock_msg_handler *umh; if (gph->version != GSMD_PROTO_VERSION) return -EINVAL; if (gph->msg_type >= __NUM_GSMD_MSGS) return -EINVAL; umh = pcmd_type_handlers[gph->msg_type]; if (!umh) return -EINVAL; return umh(gu, gph, len);}/* callback for read/write on client (libgsmd) socket */static int gsmd_usock_user_cb(int fd, unsigned int what, void *data){ struct gsmd_user *gu = data; /* FIXME: check some kind of backlog and limit it */ if (what & GSMD_FD_READ) { char buf[1024]; int rcvlen; /* read data from socket, determine what he wants */ rcvlen = read(fd, buf, sizeof(buf)); if (rcvlen == 0) { DEBUGP("EOF, this client has just vanished\n"); /* EOF, this client has just vanished */ gsmd_unregister_fd(&gu->gfd); close(fd); /* finish pending atcmd's from this client thus * destroying references to the user structure. */ atcmd_terminate_matching(gu->gsmd, gu); /* destroy whole user structure */ llist_del(&gu->list); talloc_free(gu); return 0; } else if (rcvlen < 0) return rcvlen; else return usock_rcv_pcmd(gu, buf, rcvlen); } if (what & GSMD_FD_WRITE) { /* write data from pending replies to socket */ struct gsmd_ucmd *ucmd, *uctmp; llist_for_each_entry_safe(ucmd, uctmp, &gu->finished_ucmds, list) { int rc; rc = write(fd, &ucmd->hdr, sizeof(ucmd->hdr) + ucmd->hdr.len); if (rc < 0) { DEBUGP("write return %d\n", rc); return rc; } if (rc == 0) { DEBUGP("write returns zero!!\n"); break; } if (rc != sizeof(ucmd->hdr) + ucmd->hdr.len) { DEBUGP("short write\n"); break; } DEBUGP("successfully sent cmd %p to user %p, freeing\n", ucmd, gu); llist_del(&ucmd->list); talloc_free(ucmd); } if (llist_empty(&gu->finished_ucmds)) gu->gfd.when &= ~GSMD_FD_WRITE; } return 0;}/* callback for read on master-listen-socket */static int gsmd_usock_cb(int fd, unsigned int what, void *data){ struct gsmd *g = data; struct gsmd_user *newuser; /* FIXME: implement this */ if (what & GSMD_FD_READ) { /* new incoming connection */ newuser = talloc(__gu_ctx, struct gsmd_user); if (!newuser) return -ENOMEM; newuser->gfd.fd = accept(fd, NULL, 0); if (newuser->gfd.fd < 0) { DEBUGP("error accepting incoming conn: `%s'\n", strerror(errno)); talloc_free(newuser); } newuser->gfd.when = GSMD_FD_READ; newuser->gfd.data = newuser; newuser->gfd.cb = &gsmd_usock_user_cb; newuser->gsmd = g; newuser->subscriptions = 0xffffffff; INIT_LLIST_HEAD(&newuser->finished_ucmds); llist_add(&newuser->list, &g->users); gsmd_register_fd(&newuser->gfd); } return 0;}/* handling of socket with incoming client connections */int usock_init(struct gsmd *g){ struct sockaddr_un sun; int fd, rc; __ucmd_ctx = talloc_named_const(gsmd_tallocs, 1, "ucmd"); __gu_ctx = talloc_named_const(gsmd_tallocs, 1, "gsmd_user"); fd = socket(PF_UNIX, GSMD_UNIX_SOCKET_TYPE, 0); if (fd < 0) return fd; memset(&sun, 0, sizeof(sun)); sun.sun_family = AF_UNIX; memcpy(sun.sun_path, GSMD_UNIX_SOCKET, sizeof(GSMD_UNIX_SOCKET)); rc = bind(fd, (struct sockaddr *)&sun, sizeof(sun)); if (rc < 0) { close(fd); return rc; } rc = listen(fd, 10); if (rc < 0) { close(fd); return rc; } g->gfd_sock.fd = fd; g->gfd_sock.when = GSMD_FD_READ | GSMD_FD_EXCEPT; g->gfd_sock.data = g; g->gfd_sock.cb = &gsmd_usock_cb; return gsmd_register_fd(&g->gfd_sock);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?