common: prevent buffer overflow
[supercollider.git] / include / common / scsynthsend.h
blob758742d19c9df26753fd5264a589c7487d9694bf
1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #ifndef _scpacket_
22 #define _scpacket_
24 #include "SC_Endian.h"
25 #include "SC_Types.h"
26 #include <stdexcept>
27 #include <cstring>
29 struct netaddr {
30 int socket;
31 int addr;
32 int port;
34 typedef struct netaddr netaddr;
37 template <int MaxPacketSize = 8192>
38 struct scpacket {
39 static const int kBufSize = MaxPacketSize / sizeof(int32); // round down
40 int32 *wrpos, *endpos, *msgsizepos;
41 char *tagwrpos;
42 int inbundle;
43 int32 buf[kBufSize];
45 void throw_overflow_exception()
47 throw std::runtime_error("buffer overflow");
50 scpacket() { reset(); }
51 void reset()
53 wrpos = buf;
54 endpos = buf + kBufSize;
55 inbundle = 0;
57 void addi(int i)
59 if (wrpos >= endpos) throw_overflow_exception();
60 *wrpos++ = htonl(i);
62 void addii(int64 ii)
64 int i;
65 i = (int)(ii >> 32);
66 addi(i);
67 i = (int)ii;
68 addi(i);
70 void addf(float f)
72 if (wrpos >= endpos) throw_overflow_exception();
73 elem32 slot;
74 slot.f = f;
75 *wrpos++ = htonl(slot.i);
77 void addd(double f)
79 if (wrpos >= endpos) throw_overflow_exception();
80 elem64 slot;
81 slot.f = f;
82 *wrpos++ = htonl(slot.i >> 32);
83 *wrpos++ = htonl(slot.i & 0x00000000FFFFFFFF);
85 void adds(const char *src)
87 size_t len = strlen(src);
88 size_t len4 = (len + 4) >> 2;
89 if (wrpos + len4 > endpos) throw_overflow_exception();
90 wrpos[len4 - 1] = 0;
91 memcpy(wrpos, src, len);
92 wrpos += len4;
94 void adds_slpre(const char *src) // prepends a slash
96 size_t len = strlen(src);
97 size_t len4 = (len + 5) >> 2;
98 if (wrpos + len4 > endpos) throw_overflow_exception();
99 wrpos[len4 - 1] = 0;
100 char* wrpos_c = (char*)wrpos;
101 *wrpos_c = '/';
102 memcpy(wrpos_c+1, src, len);
103 wrpos += len4;
105 void adds(const char *src, size_t len)
107 size_t len4 = (len + 4) >> 2;
108 if (wrpos + len4 > endpos) throw_overflow_exception();
109 wrpos[len4 - 1] = 0;
110 memcpy(wrpos, src, len);
111 wrpos += len4;
113 void addb(uint8 *src, size_t len)
115 size_t len4 = (len + 3) >> 2;
116 if (wrpos + (len4 + 1) > endpos) throw_overflow_exception();
117 wrpos[len4 - 1] = 0;
118 int32 swaplen = len;
119 *wrpos++ = htonl(swaplen);
120 memcpy(wrpos, src, len);
121 wrpos += len4;
123 void addtag(char c) { *tagwrpos++ = c; }
124 void skip(int n)
126 if (wrpos + n > endpos) throw_overflow_exception();
127 wrpos += n;
129 void maketags(int n)
131 int size4 = (n + 4) >> 2;
132 tagwrpos = (char*)wrpos;
133 skip(size4);
134 wrpos[-1] = 0;
136 int size() { return (char*)wrpos - (char*)buf; }
137 char* data() { return (char*)buf; }
139 void OpenBundle(int64 time)
141 inbundle++;
142 adds("#bundle");
143 addii(time);
145 void CloseBundle()
147 if (inbundle) inbundle--;
150 void BeginMsg()
152 if (inbundle) {
153 msgsizepos = wrpos;
154 addi(0);
157 void EndMsg()
159 if (inbundle) {
160 *msgsizepos = htonl(((wrpos - msgsizepos) - 1) * sizeof(int32));
165 typedef scpacket<> small_scpacket;
166 typedef scpacket<65516> big_scpacket;
169 #endif