소스 검색

- added missing pt.c

Andrei Pelinescu-Onciul 19 년 전
부모
커밋
02a2f864c1
1개의 변경된 파일272개의 추가작업 그리고 0개의 파일을 삭제
  1. 272 0
      pt.c

+ 272 - 0
pt.c

@@ -0,0 +1,272 @@
+/*
+ * $Id$
+ *
+ * Process Table
+ *
+ *
+ *
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+/*
+ * History:
+ * --------
+ *  2006-06-14	added process table in shared mem (dragos)
+ */
+
+
+#include "pt.h"
+#include "tcp_init.h"
+#include "sr_module.h"
+
+#include "stdio.h"
+
+
+static int estimated_proc_no=0;
+
+/* returns 0 on success, -1 on error */
+int init_pt(int proc_no)
+{
+	estimated_proc_no+=proc_no;
+	/*alloc pids*/
+#ifdef SHM_MEM
+	pt=shm_malloc(sizeof(struct process_table)*estimated_proc_no);
+	process_count = shm_malloc(sizeof(int));
+#else
+	pt=pkg_malloc(sizeof(struct process_table)*estimated_proc_no);
+	process_count = pkg_malloc(sizeof(int));
+#endif
+	process_lock = lock_alloc();
+	process_lock = lock_init(process_lock);
+	if (pt==0||process_count==0||process_lock==0){
+		LOG(L_ERR, "ERROR: out  of memory\n");
+		return -1;
+	}
+	memset(pt, 0, sizeof(struct process_table)*estimated_proc_no);
+
+	process_no=0; /*main process number*/
+	pt[process_no].pid=getpid();
+	memcpy(pt[*process_count].desc,"main",5);
+	*process_count=1;
+	return 0;
+}
+
+
+/* register no processes, used from mod_init when processes will be forked
+ *  from mod_child 
+ *  returns 0 on success, -1 on error
+ */
+int register_procs(int no)
+{
+	if (pt){
+		LOG(L_CRIT, "BUG: register_procs(%d) called at runtime\n", no);
+		return -1;
+	}
+	estimated_proc_no+=no;
+	return 0;
+}
+
+
+
+/* returns the maximum number of processes */
+int get_max_procs()
+{
+	return estimated_proc_no;
+}
+
+
+/* return processes pid */
+inline int my_pid()
+{
+	return pt ? pt[process_no].pid : getpid();
+}
+
+/**
+ * Forks a new process.
+ * @param child_id - rank, if equal to PROC_NOCHLDINIT init_child will not be
+ *                   called for the new forked process (see sr_module.h)
+ * @param desc - text description for the process table
+ * @param make_sock - if to create a unix socket pair for it
+ * @returns the pid of the new process
+ */
+inline int fork_process(int child_id, char *desc, int make_sock)
+{
+	int pid,old_process_no;
+#ifdef USE_TCP
+	int sockfd[2];
+#endif
+
+	lock_get(process_lock);	
+	if (*process_count>=estimated_proc_no) {
+		LOG(L_CRIT, "ERROR: fork_process(): Process limit of %d exceeded."
+					" Will simulate fork fail.\n", estimated_proc_no);
+		lock_release(process_lock);
+		return -1;
+	}	
+	
+	#ifdef USE_TCP
+		if(make_sock && !tcp_disable){
+			 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){
+				LOG(L_ERR, "ERROR: fork_process(): socketpair failed: %s\n",
+					strerror(errno));
+				return -1;
+			}
+		}
+	#endif
+	
+	old_process_no = process_no;
+	process_no = *process_count;
+	pid = fork();
+	if (pid<0) {
+		lock_release(process_lock);
+		return pid;
+	}
+	if (pid==0){
+		/* child */
+		/* wait for parent to get out of critical zone.
+		 * this is actually relevant as the parent updates
+		 * the pt & process_count. */
+		lock_get(process_lock);
+		#ifdef USE_TCP
+			if (make_sock && !tcp_disable){
+				close(sockfd[0]);
+				unix_tcp_sock=sockfd[1];
+			}
+		#endif		
+		lock_release(process_lock);	
+		if ((child_id!=PROC_NOCHLDINIT) && (init_child(child_id) < 0)) {
+			LOG(L_ERR, "ERROR: fork_process(): init_child failed for %s\n",
+						pt[process_no].desc);
+			return -1;
+		}
+		return pid;
+	} else {
+		/* parent */
+		process_no = old_process_no;
+		/* add the process to the list in shm */
+		pt[*process_count].pid=pid;
+		if (desc){
+			strncpy(pt[*process_count].desc, desc, MAX_PT_DESC);
+		}
+		#ifdef USE_TCP
+			if (make_sock && !tcp_disable){
+				close(sockfd[1]);
+				pt[*process_count].unix_sock=sockfd[0];
+				pt[*process_count].idx=-1; /* this is not "tcp" process*/
+			}
+		#endif		
+		*process_count = (*process_count) +1;
+		lock_release(process_lock);
+		return pid;
+	}
+}
+
+/**
+ * Forks a new TCP process.
+ * @param desc - text description for the process table
+ * @param r - index in the tcp_children array
+ * @param *reader_fd_1 - pointer to return the reader_fd[1]
+ * @returns the pid of the new process
+ */
+inline int fork_tcp_process(int child_id,char *desc,int r,int *reader_fd_1)
+{
+	int pid,old_process_no;
+	int sockfd[2];
+	int reader_fd[2]; /* for comm. with the tcp children read  */
+
+
+	
+	lock_get(process_lock);
+	/* set the local process_no */
+	if (*process_count>=estimated_proc_no) {
+		LOG(L_CRIT, "ERROR: fork_tcp_process(): Process limit of %d exceeded."
+					" Simulating fork fail\n", estimated_proc_no);
+		return -1;
+	}	
+	
+	if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){
+		LOG(L_ERR, "ERROR: fork_tcp_process(): socketpair failed: %s\n",
+					strerror(errno));
+		return -1;
+	}
+	if (socketpair(AF_UNIX, SOCK_STREAM, 0, reader_fd)<0){
+		LOG(L_ERR, "ERROR: fork_tcp_process(): socketpair failed: %s\n",
+					strerror(errno));
+		return -1;
+	}
+	if (tcp_fix_child_sockets(reader_fd)<0){
+		LOG(L_ERR, "ERROR: fork_tcp_process(): failed to set non blocking"
+					"on child sockets\n");
+		/* continue, it's not critical (it will go slower under
+		 * very high connection rates) */
+	}
+	
+	old_process_no = process_no;
+	process_no = *process_count;
+	pid = fork();
+	if (pid<0) {
+		lock_release(process_lock);
+		return pid;
+	}
+	if (pid==0){
+		/* wait for parent to get out of critical zone */
+		lock_get(process_lock);
+			close(sockfd[0]);
+			unix_tcp_sock=sockfd[1];
+			if (reader_fd_1) *reader_fd_1=reader_fd[1];
+		lock_release(process_lock);
+		if (init_child(child_id) < 0) {
+			LOG(L_ERR, "ERROR: fork_tcp_process(): init_child failed for "
+					"%s\n", pt[process_no].desc);
+			return -1;
+		}
+		return pid;
+	} else {
+		/* parent */		
+		process_no = old_process_no;
+		/* add the process to the list in shm */
+		pt[*process_count].pid=pid;
+		pt[*process_count].unix_sock=sockfd[0];
+		pt[*process_count].idx=r; 	
+		if (desc){
+			snprintf(pt[*process_count].desc, MAX_PT_DESC, "%s child=%d", 
+						desc, r);
+		}
+		
+		close(sockfd[1]);
+		close(reader_fd[1]);
+		
+		tcp_children[r].pid=pid;
+		tcp_children[r].proc_no=process_no;
+		tcp_children[r].busy=0;
+		tcp_children[r].n_reqs=0;
+		tcp_children[r].unix_sock=reader_fd[0];
+		
+		*process_count = (*process_count) +1;
+		lock_release(process_lock);
+		return pid;
+	}
+}
+
+
+