jabberd2
2.2.16
|
00001 /* vim: set noet ts=4 sw=4: */ 00002 /* 00003 * jabberd - Jabber Open Source Server 00004 * Copyright (c) 2009 Tomasz Sterna 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA 00019 */ 00020 00028 #include "c2s.h" 00029 00030 #define COMMANDLINE_LENGTH_MAX 2048 00031 static void _pbx_close_pipe(c2s_t c2s); 00032 static void _pbx_open_pipe(c2s_t c2s, int mode); 00033 static void _pbx_read_pipe(c2s_t c2s); 00034 static void _pbx_write_pipe(c2s_t c2s); 00035 int _pbx_process_command(c2s_t c2s, char *cmd); 00036 00037 static void _pbx_read_command(c2s_t c2s) { 00038 char buf[COMMANDLINE_LENGTH_MAX]; 00039 char *bufp; 00040 00041 bufp = (char*)&buf; 00042 while (read(c2s->pbx_pipe_fd, bufp, 1) > 0) 00043 if(bufp - ((char*)&buf) < COMMANDLINE_LENGTH_MAX-1) bufp++; 00044 *bufp = '\0'; 00045 00046 log_debug(ZONE, "command read: %s", buf); 00047 00048 _pbx_close_pipe(c2s); 00049 00050 if(_pbx_process_command(c2s, buf) == 0) 00051 _pbx_write_pipe(c2s); 00052 00053 _pbx_read_pipe(c2s); 00054 } 00055 00056 static int _pbx_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg) { 00057 c2s_t c2s = (c2s_t) arg; 00058 00059 log_debug(ZONE, "action %s on PBX pipe", a==0?"action_ACCEPT":a==1?"action_READ":a==2?"action_WRITE":a==3?"action_CLOSE":"-unknown-"); 00060 00061 switch(a) { 00062 case action_READ: 00063 log_debug(ZONE, "read action on fd %d", fd->fd); 00064 _pbx_read_command(c2s); 00065 return 1; /* want to read again */ 00066 00067 case action_WRITE: 00068 /* write buffered lines from jqueue */ 00069 _pbx_close_pipe(c2s); 00070 return 0; 00071 00072 case action_CLOSE: 00073 c2s->pbx_pipe_mio_fd = 0; 00074 c2s->pbx_pipe_fd = -1; 00075 return 0; 00076 00077 default: 00078 break; 00079 } 00080 00081 return 0; 00082 } 00083 00084 static void _pbx_close_pipe(c2s_t c2s) { 00085 log_debug(ZONE, "### close_pipe"); 00086 if(c2s->pbx_pipe_mio_fd) 00087 mio_close(c2s->mio, c2s->pbx_pipe_mio_fd); 00088 } 00089 00090 static void _pbx_open_pipe(c2s_t c2s, int mode) { 00091 #ifdef WIN32 00092 log_debug(ZONE, "PBX is not supported under Windows"); 00093 log_write(c2s->log, LOG_ERR, "PBX for Windows is not supported yet"); 00094 exit(EXIT_FAILURE); 00095 #else 00096 log_debug(ZONE, "### open_pipe"); 00097 c2s->pbx_pipe_fd = open(c2s->pbx_pipe, mode | O_NONBLOCK); 00098 if(c2s->pbx_pipe_fd == -1) { 00099 c2s->pbx_pipe_mio_fd = 0; 00100 log_debug(ZONE, "error opening pipe: %d %s", errno, strerror(errno)); 00101 log_write(c2s->log, LOG_ERR, "failed to open PBX named pipe %s for %s", c2s->pbx_pipe, mode==O_RDONLY?"reading":"writing"); 00102 exit(EXIT_FAILURE); 00103 } else 00104 c2s->pbx_pipe_mio_fd = mio_register(c2s->mio, c2s->pbx_pipe_fd, _pbx_mio_callback, (void *) c2s); 00105 #endif 00106 } 00107 /* open pipe for reading */ 00108 static void _pbx_read_pipe(c2s_t c2s) { 00109 log_debug(ZONE, "### read_pipe"); 00110 _pbx_open_pipe(c2s, O_RDONLY); 00111 mio_read(c2s->mio, c2s->pbx_pipe_mio_fd); 00112 } 00113 /* trigger buffer write */ 00114 static void _pbx_write_pipe(c2s_t c2s) { 00115 log_debug(ZONE, "### write_pipe"); 00116 _pbx_open_pipe(c2s, O_RDWR); 00117 mio_write(c2s->mio, c2s->pbx_pipe_mio_fd); 00118 } 00119 00120 void c2s_pbx_init(c2s_t c2s) { 00121 #ifdef WIN32 00122 log_debug(ZONE, "PBX is not supported under Windows"); 00123 log_write(c2s->log, LOG_ERR, "PBX for Windows is not supported yet"); 00124 exit(EXIT_FAILURE); 00125 #else 00126 struct stat sb; 00127 00128 /* create the FIFO */ 00129 if(stat(c2s->pbx_pipe, &sb) == -1) { 00130 if(mkfifo(c2s->pbx_pipe, S_IRUSR | S_IWUSR | S_IRGRP) == -1) { 00131 log_write(c2s->log, LOG_ERR, "failed to create PBX named pipe: %s", c2s->pbx_pipe); 00132 exit(EXIT_FAILURE); 00133 } 00134 }else{ 00135 if(!S_ISFIFO(sb.st_mode)) { 00136 log_write(c2s->log, LOG_ERR, "file %s exists but is not a named pipe", c2s->pbx_pipe); 00137 exit(EXIT_FAILURE); 00138 } 00139 } 00140 00141 _pbx_read_pipe(c2s); 00142 #endif 00143 }