[Ttssh2-commit] [6208] ssh agent 転送で複数接続に対応。

アーカイブの一覧に戻る

svnno****@sourc***** svnno****@sourc*****
2015年 12月 14日 (月) 17:11:16 JST


Revision: 6208
          http://sourceforge.jp/projects/ttssh2/scm/svn/commits/6208
Author:   doda
Date:     2015-12-14 17:11:16 +0900 (Mon, 14 Dec 2015)
Log Message:
-----------
ssh agent 転送で複数接続に対応。

Modified Paths:
--------------
    trunk/cygterm/README
    trunk/cygterm/README-j
    trunk/cygterm/cygterm.cc

-------------- next part --------------
Modified: trunk/cygterm/README
===================================================================
--- trunk/cygterm/README	2015-12-14 08:05:10 UTC (rev 6207)
+++ trunk/cygterm/README	2015-12-14 08:11:16 UTC (rev 6208)
@@ -266,6 +266,9 @@
                 zsh 4.3.10
 
 // C H A N G E S //
+v1.07_26 2015/12/14 (by doda)
+        * Add multiple connections support for the ssh-agent proxy.
+
 v1.07_25 2015/02/21 (by doda)
         * Bug fix: The TERM environment variable can not be configured.
 

Modified: trunk/cygterm/README-j
===================================================================
--- trunk/cygterm/README-j	2015-12-14 08:05:10 UTC (rev 6207)
+++ trunk/cygterm/README-j	2015-12-14 08:11:16 UTC (rev 6208)
@@ -278,7 +278,10 @@
                 zsh 4.3.10
 
 // $BJQ(B $B99(B $BMz(B $BNr(B //
-v1.07_25 2015/02/21 (by maya)
+v1.07_26 2015/12/14 (by doda)
+        * ssh $BG'>Z%(!<%8%'%s%HE>Aw$GJ#?t%3%M%/%7%g%s$KBP1~$7$?!#(B
+
+v1.07_25 2015/02/21 (by doda)
         * TERM $B4D6-JQ?t$, @ 5$7$/@_Dj$5$l$k$h$&$K$7$?!#(B
 
 v1.07_24 2013/08/15 (by maya)

Modified: trunk/cygterm/cygterm.cc
===================================================================
--- trunk/cygterm/cygterm.cc	2015-12-14 08:05:10 UTC (rev 6207)
+++ trunk/cygterm/cygterm.cc	2015-12-14 08:11:16 UTC (rev 6208)
@@ -33,7 +33,7 @@
 //
 
 static char Program[] = "CygTerm+";
-static char Version[] = "version 1.07_25 (2015/02/21)";
+static char Version[] = "version 1.07_26 (2015/12/14)";
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -525,18 +525,68 @@
 	exit(0);
 };
 
-//=================//
-// ssh-agent proxy //
-//-----------------//
+struct connList {
+	int sock;
+	int recvlen;
+	int sendlen;
+	struct connList *next;
+	unsigned char ibuff[AGENT_MAX_MSGLEN];
+	unsigned char obuff[AGENT_MAX_MSGLEN];
+};
+
+int proc_recvd(struct connList *conn)
+{
+	int reqlen, len;
+
+	if (conn->sendlen > 0) {
+		return 0;
+	}
+
+	if (conn->recvlen < 4) {
+		return 0;
+	}
+
+	reqlen = get_uint32(conn->ibuff) + 4;
+	if (conn->recvlen < reqlen) {
+		return 0;
+	}
+
+	len = agent_request(conn->obuff, sizeof(conn->obuff), conn->ibuff);
+
+	if (len > 0) {
+		conn->sendlen = len;
+	}
+	else {
+		set_uint32(conn->obuff, 1);
+		conn->obuff[4] = 5; // SSH_AGENT_FAILURE
+		conn->sendlen = 1;
+	}
+
+	if (conn->recvlen == reqlen) {
+		conn->recvlen = 0;
+	}
+	else {
+		conn->recvlen -= reqlen;
+		memmove(conn->ibuff, conn->ibuff + reqlen, conn->recvlen);
+	}
+
+	return 1;
+}
+
 void agent_proxy()
 {
-	int sock, asock;
-	unsigned long readlen, reqlen, recvlen;
+	int sock, asock, ret;
+	long len;
+	unsigned long reqlen;
 	struct sockaddr_un addr;
-	unsigned char buff[AGENT_MAX_MSGLEN];
+	unsigned char tmpbuff[AGENT_MAX_MSGLEN];
+	struct connList connections, *new_conn, *prev, *cur;
+	fd_set readfds, writefds, rfds, wfds;
 	struct sigaction act;
 	sigset_t blk;
 
+	connections.next = NULL;
+
 	if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
 		msg_print("socket failed.");
 		exit(0);
@@ -564,46 +614,113 @@
 	sigaction(SIGHUP, &act, NULL);
 	sigaction(SIGQUIT, &act, NULL);
 
+	FD_ZERO(&readfds);
+	FD_ZERO(&writefds);
+	FD_SET(sock, &readfds);
+
 	while (1) {
-		if ((asock = accept(sock, NULL, NULL)) < 0) {
-			switch (errno) {
-			case EINTR:
-			case ECONNABORTED:
-				continue;
+		memcpy(&rfds, &readfds, sizeof(fd_set));
+		memcpy(&wfds, &writefds, sizeof(fd_set));
+
+		select(FD_SETSIZE, &rfds, &wfds, NULL, NULL);
+
+		if (FD_ISSET(sock, &rfds)) {
+			asock = accept(sock, NULL, NULL);
+			if (asock < 0) {
+				if (!(errno == EINTR || errno == ECONNABORTED)) {
+					break;
+				}
 			}
-			break;
+			else {
+				new_conn = (struct connList *)malloc(sizeof(struct connList));
+				if (new_conn == NULL) {
+					// no memory
+					close(sock);
+				}
+				else {
+					new_conn->sock = asock;
+					new_conn->recvlen = 0;
+					new_conn->sendlen = 0;
+					new_conn->next = connections.next;
+					connections.next = new_conn;
+					FD_SET(asock, &readfds);
+				}
+			}
 		}
-		recvlen = 0;
-		while ((readlen = read(asock, buff+recvlen, 4-recvlen)) > 0) {
-			recvlen += readlen;
-			if (recvlen < 4) {
-				continue;
-			}
-			recvlen = 0;
-			reqlen = get_uint32(buff);
-			while ((readlen = read(asock, buff+4+recvlen, reqlen-recvlen)) > 0) {
-				recvlen += readlen;
-				if (recvlen < reqlen) {
-					continue;
-				}
 
-				sigprocmask(SIG_BLOCK, &blk, NULL);
-				readlen = agent_request(buff, sizeof(buff), buff);
-				sigprocmask(SIG_UNBLOCK, &blk, NULL);
+		prev = &connections;
+		for (cur=connections.next; cur != NULL; cur = cur->next) {
+			if (FD_ISSET(cur->sock, &wfds)) {
+				if (cur->sendlen > 0) {
+					len = send(cur->sock, cur->obuff, cur->sendlen, 0);
+					if (len < 0) {
+						// write error
+						prev->next = cur->next;
+						shutdown(cur->sock, SHUT_RDWR);
+						close(cur->sock);
+						FD_CLR(cur->sock, &writefds);
+						FD_CLR(cur->sock, &readfds);
+						free(cur);
+						cur = prev;
+						continue;
+					}
+					else if (len >= cur->sendlen) {
+						cur->sendlen = 0;
 
-				if (readlen > 0) {
-					write(asock, buff, readlen);
+						sigprocmask(SIG_BLOCK, &blk, NULL);
+						ret = proc_recvd(cur);
+						sigprocmask(SIG_UNBLOCK, &blk, NULL);
+
+						if (ret) {
+							FD_SET(cur->sock, &writefds);
+							FD_CLR(cur->sock, &readfds);
+						}
+						else {
+							FD_CLR(cur->sock, &writefds);
+							FD_SET(cur->sock, &readfds);
+						}
+					}
+					else if (len > 0) {
+						cur->sendlen -= len;
+						memmove(cur->obuff, cur->obuff+len, cur->sendlen);
+					}
 				}
 				else {
-					set_uint32(buff, 1);
-					buff[4] = 5; // SSH_AGENT_FAILURE
-					write(asock, buff, 5);
+					FD_CLR(cur->sock, &writefds);
 				}
 			}
-			recvlen = 0;
+
+			if (FD_ISSET(cur->sock, &rfds)) {
+				len = recv(cur->sock, cur->ibuff + cur->recvlen, sizeof(cur->ibuff) - cur->recvlen, 0);
+				if (len > 0) {
+					cur->recvlen += len;
+
+					sigprocmask(SIG_BLOCK, &blk, NULL);
+					ret = proc_recvd(cur);
+					sigprocmask(SIG_UNBLOCK, &blk, NULL);
+
+					if (ret) {
+						FD_SET(cur->sock, &writefds);
+						FD_CLR(cur->sock, &readfds);
+					}
+					else {
+						FD_CLR(cur->sock, &writefds);
+						FD_SET(cur->sock, &readfds);
+					}
+				}
+				else if (len < 0) {
+					// read error
+					prev->next = cur->next;
+					shutdown(cur->sock, SHUT_RDWR);
+					close(cur->sock);
+					FD_CLR(cur->sock, &readfds);
+					FD_CLR(cur->sock, &writefds);
+					free(cur);
+					cur = prev;
+					continue;
+				}
+			}
 		}
-		shutdown(asock, SHUT_RDWR);
-		close(asock);
 	}
 
 agent_thread_cleanup:



Ttssh2-commit メーリングリストの案内
アーカイブの一覧に戻る