Merge branch 'jc/autogc'
[git] / sideband.c
1 #include "pkt-line.h"
2 #include "sideband.h"
3
4 /*
5  * Receive multiplexed output stream over git native protocol.
6  * in_stream is the input stream from the remote, which carries data
7  * in pkt_line format with band designator.  Demultiplex it into out
8  * and err and return error appropriately.  Band #1 carries the
9  * primary payload.  Things coming over band #2 is not necessarily
10  * error; they are usually informative message on the standard error
11  * stream, aka "verbose").  A message over band #3 is a signal that
12  * the remote died unexpectedly.  A flush() concludes the stream.
13  */
14 int recv_sideband(const char *me, int in_stream, int out, int err)
15 {
16         char buf[7 + LARGE_PACKET_MAX + 1];
17         strcpy(buf, "remote:");
18         while (1) {
19                 int band, len;
20                 len     = packet_read_line(in_stream, buf+7, LARGE_PACKET_MAX);
21                 if (len == 0)
22                         break;
23                 if (len < 1) {
24                         len = sprintf(buf, "%s: protocol error: no band designator\n", me);
25                         safe_write(err, buf, len);
26                         return SIDEBAND_PROTOCOL_ERROR;
27                 }
28                 band = buf[7] & 0xff;
29                 len--;
30                 switch (band) {
31                 case 3:
32                         buf[7] = ' ';
33                         buf[8+len] = '\n';
34                         safe_write(err, buf, 8+len+1);
35                         return SIDEBAND_REMOTE_ERROR;
36                 case 2:
37                         buf[7] = ' ';
38                         safe_write(err, buf, 8+len);
39                         continue;
40                 case 1:
41                         safe_write(out, buf+8, len);
42                         continue;
43                 default:
44                         len = sprintf(buf,
45                                       "%s: protocol error: bad band #%d\n",
46                                       me, band);
47                         safe_write(err, buf, len);
48                         return SIDEBAND_PROTOCOL_ERROR;
49                 }
50         }
51         return 0;
52 }
53
54 /*
55  * fd is connected to the remote side; send the sideband data
56  * over multiplexed packet stream.
57  */
58 ssize_t send_sideband(int fd, int band, const char *data, ssize_t sz, int packet_max)
59 {
60         ssize_t ssz = sz;
61         const char *p = data;
62
63         while (sz) {
64                 unsigned n;
65                 char hdr[5];
66
67                 n = sz;
68                 if (packet_max - 5 < n)
69                         n = packet_max - 5;
70                 sprintf(hdr, "%04x", n + 5);
71                 hdr[4] = band;
72                 safe_write(fd, hdr, 5);
73                 safe_write(fd, p, n);
74                 p += n;
75                 sz -= n;
76         }
77         return ssz;
78 }