1 
2 /*
3  *  Diverse Bristol midi routines.
4  *  Copyright (c) by Nick Copeland <nickycopeland@hotmail.com> 1996,2012
5  *
6  *
7  *   This program is free software; you can redistribute it and/or modify
8  *   it under the terms of the GNU General Public License as published by
9  *   the Free Software Foundation; either version 3 of the License, or
10  *   (at your option) any later version.
11  *
12  *   This program is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with this program; if not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 /*#define DEBUG */
23 
24 #include <sys/unistd.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <sys/stat.h>
28 #include <sys/un.h>
29 #include <string.h>
30 #include <stdio.h>
31 #include <fcntl.h>
32 
33 #include "bristol.h"
34 #include "bristolmidi.h"
35 
36 extern bristolMidiMain bmidi;
37 extern int open_remote_socket(char *, int, int, int);
38 extern int bristolMidiFindDev(char *);
39 extern int bristolMidiFindFreeHandle();
40 
41 static char bristol_sockname[128];
42 
43 int
bristolMidiTCPPassive(char * devname,int conntype,int chan,int msgs,int (* callback)(),void * param,int dev,int handle)44 bristolMidiTCPPassive(char *devname, int conntype, int chan, int msgs,
45 int (*callback)(), void *param, int dev, int handle)
46 {
47 	struct sockaddr address;
48 
49 	//printf("bristolMidiTCPPassive(%s, %i, %i)\n", devname, dev, handle);
50 
51 	if ((conntype & BRISTOL_CONN_UNIX) ||
52 		((strncmp("unix", devname, 4) == 0)
53 		&& (strlen(devname) > 4)
54 		&& (devname[4] == ':')))
55 		conntype = 0;
56 	else
57 		conntype = 1;
58 
59 	if (chan <= 0)
60 		chan = 5028;
61 
62 	if (conntype)
63 	{
64 		int count = 0;
65 
66 		while ((bmidi.dev[dev].fd = open_remote_socket(devname, chan, 8, -1))
67 			< 0)
68 		{
69 			printf("Could not open control socket, count %i\n", count);
70 			if (--count <= 0)
71 				break;
72 			sleep(10);
73 		}
74 
75 		if (bmidi.dev[dev].fd < 0)
76 		{
77 			printf("No controlling socket available: anticipating MIDI\n");
78 			return(-1);
79 		} else
80 			printf("Opened listening control socket: %i\n", chan);
81 	} else {
82 		/*
83 		 * Open a unix domain control socket.
84 		 */
85 		unlink(devname);
86 
87 		if ((bmidi.dev[dev].fd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0)
88 		{
89 			printf("Could not get control socket\n");
90 			return(BRISTOL_MIDI_DEVICE);
91 		}
92 
93 		/*
94 		 * Make it non-blocking
95 		 */
96 		if (fcntl(bmidi.dev[dev].fd, F_SETFL, O_NONBLOCK|O_ASYNC) < 0)
97 			printf("Could not set non-blocking\n");
98 
99 		printf("Opened Unix named control socket\n");
100 
101 		address.sa_family = AF_LOCAL;
102 		if ((strlen(devname) > 5) && (devname[4] == ':'))
103 			snprintf(bristol_sockname, 64, "/tmp/br.%s", &devname[5]);
104 		else
105 			sprintf(bristol_sockname, "%s", BRISTOL_SOCKNAME);
106 
107 		snprintf(&address.sa_data[0], 14, "%s", bristol_sockname);
108 
109 		if (bind(bmidi.dev[dev].fd, &address, sizeof(struct sockaddr)))
110 			printf("Could not bind name: %s\n", bristol_sockname);
111 		else
112 			printf("Bound name to socket: %s\n", bristol_sockname);
113 
114 		if (listen(bmidi.dev[dev].fd, 8) < 0)
115 			printf("Could not configure listens\n");
116 		else
117 			printf("Activated listens on socket\n");
118 
119 		/*
120 		 * Make it world read/writeable.
121 		 */
122 		chmod(devname, 0777);
123 	}
124 
125 	/*
126 	 * Configure this device as used, with decoding using the ALSA interface.
127 	 * We use ALSA basically since it workd.
128 	 */
129 	bmidi.dev[dev].flags = BRISTOL_ACCEPT_SOCKET|BRISTOL_CONN_TCP;
130 
131 	return(handle);
132 }
133 
134 int
acceptConnection(int acceptdev)135 acceptConnection(int acceptdev)
136 {
137 	int dev, handle, chandle;
138 	socklen_t addrlen;
139 	struct sockaddr address;
140 	struct linger blinger;
141 
142 	/*
143 	 * We have read on the control socket, attempt to accept the connection.
144 	 */
145 	while ((dev = bristolMidiFindDev(NULL)) < 0)
146 	{
147 		printf("No dev available for accept()\n");
148 		/*
149 		 * We cannot leave the socket dangling, otherwise we get into a closed
150 		 * loop of accept failing.
151 		 */
152 		close(accept(bmidi.dev[acceptdev].fd, &address, &addrlen));
153 		return(-1);
154 	}
155 
156 	addrlen = sizeof(struct sockaddr);
157 
158 	if ((bmidi.dev[dev].fd =
159 		accept(bmidi.dev[acceptdev].fd, &address, &addrlen)) < 0)
160 	{
161 		//printf("No accepts waiting\n");
162 		return(-1);
163 	}
164 
165 	bmidi.dev[dev].state = BRISTOL_MIDI_OK;
166 	bmidi.dev[dev].handleCount = 1;
167 	bmidi.dev[dev].flags = BRISTOL_CONN_TCP|BRISTOL_CONTROL_SOCKET;
168 
169 	printf("Accepted connection from %i (%i) onto %i (%i)\n",
170 		acceptdev, bmidi.dev[acceptdev].fd, dev, bmidi.dev[dev].fd);
171 
172 	/*
173 	 * Make sure we have a handle available
174 	 */
175 	if ((handle = bristolMidiFindFreeHandle()) < 0)
176 		return(handle);
177 
178 	for (chandle = 0; chandle < BRISTOL_MIDI_HANDLES; chandle++)
179 	{
180 		if ((bmidi.handle[chandle].dev == acceptdev) &&
181 			(bmidi.dev[bmidi.handle[chandle].dev].flags
182 				& BRISTOL_ACCEPT_SOCKET))
183 			break;
184 	}
185 	if (chandle == BRISTOL_MIDI_HANDLES)
186 	{
187 		printf("Did not find related accept socket\n");
188 		close(bmidi.dev[dev].fd);
189 		bmidi.dev[dev].fd = -1;
190 		return(-1);
191 	}
192 
193 	bmidi.handle[handle].handle = handle; /* That looks kind of wierd! */
194 	bmidi.handle[handle].handle = handle; /* That looks kind of wierd! */
195 	bmidi.handle[handle].state = BRISTOL_MIDI_OK;
196 	bmidi.handle[handle].channel = bmidi.handle[chandle].channel;
197 	bmidi.handle[handle].dev = dev;
198 	bmidi.handle[handle].flags = BRISTOL_MIDI_OK;
199 	bmidi.handle[handle].messagemask = bmidi.handle[chandle].messagemask;
200 	bmidi.handle[handle].callback = bmidi.handle[chandle].callback;
201 	bmidi.handle[handle].param = bmidi.handle[chandle].param;
202 
203 	blinger.l_onoff = 1;
204 	blinger.l_linger = 2;
205 
206 	if (setsockopt(bmidi.dev[dev].fd, SOL_SOCKET, SO_LINGER,
207 		&blinger, sizeof(struct linger)) < 0)
208 		printf("server linger failed\n");
209 
210 //printf("inetServer received: %i %i %i\n", handle, bmidi.handle[handle].dev, bmidi.dev[bmidi.handle[handle].dev].fd);
211 
212 	return(0);
213 }
214 
215