netpack.c

Go to the documentation of this file.
00001 
00005 /*
00006 Copyright (C) 1997-2001 Id Software, Inc.
00007 
00008 This program is free software; you can redistribute it and/or
00009 modify it under the terms of the GNU General Public License
00010 as published by the Free Software Foundation; either version 2
00011 of the License, or (at your option) any later version.
00012 
00013 This program is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00016 
00017 See the GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with this program; if not, write to the Free Software
00021 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00022 
00023 */
00024 
00025 #include "common.h"
00026 
00027 const vec3_t bytedirs[] = {
00028 #include "../shared/vertex_normals.h"
00029 };
00030 
00031 void NET_WriteChar (struct dbuffer *buf, char c)
00032 {
00033     dbuffer_add(buf, &c, 1);
00034 }
00035 
00036 void NET_WriteByte (struct dbuffer *buf, byte c)
00037 {
00038     dbuffer_add(buf, (char *)&c, 1);
00039 }
00040 
00041 void NET_WriteShort (struct dbuffer *buf, int c)
00042 {
00043     unsigned short v = LittleShort(c);
00044     dbuffer_add(buf, (char *)&v, 2);
00045 }
00046 
00047 void NET_WriteLong (struct dbuffer *buf, int c)
00048 {
00049     int v = LittleLong(c);
00050     dbuffer_add(buf, (char *)&v, 4);
00051 }
00052 
00053 void NET_WriteString (struct dbuffer *buf, const char *str)
00054 {
00055     if (!str)
00056         dbuffer_add(buf, "", 1);
00057     else
00058         dbuffer_add(buf, str, strlen(str) + 1);
00059 }
00060 
00061 void NET_WriteRawString (struct dbuffer *buf, const char *str)
00062 {
00063     if (str)
00064         dbuffer_add(buf, str, strlen(str));
00065 }
00066 
00067 void NET_WriteCoord (struct dbuffer *buf, float f)
00068 {
00069     NET_WriteLong(buf, (int) (f * 32));
00070 }
00071 
00075 void NET_Write2Pos (struct dbuffer *buf, vec2_t pos)
00076 {
00077     NET_WriteLong(buf, (long) (pos[0] * 32.));
00078     NET_WriteLong(buf, (long) (pos[1] * 32.));
00079 }
00080 
00084 void NET_WritePos (struct dbuffer *buf, const vec3_t pos)
00085 {
00086     NET_WriteLong(buf, (long) (pos[0] * 32.));
00087     NET_WriteLong(buf, (long) (pos[1] * 32.));
00088     NET_WriteLong(buf, (long) (pos[2] * 32.));
00089 }
00090 
00091 void NET_WriteGPos (struct dbuffer *buf, const pos3_t pos)
00092 {
00093     NET_WriteByte(buf, pos[0]);
00094     NET_WriteByte(buf, pos[1]);
00095     NET_WriteByte(buf, pos[2]);
00096 }
00097 
00098 void NET_WriteAngle (struct dbuffer *buf, float f)
00099 {
00100     NET_WriteByte(buf, (int) (f * 256 / 360) & 255);
00101 }
00102 
00103 void NET_WriteAngle16 (struct dbuffer *buf, float f)
00104 {
00105     NET_WriteShort(buf, ANGLE2SHORT(f));
00106 }
00107 
00112 void NET_WriteDir (struct dbuffer *buf, const vec3_t dir)
00113 {
00114     int i, best;
00115     float bestd;
00116     size_t bytedirsLength;
00117 
00118     if (!dir) {
00119         NET_WriteByte(buf, 0);
00120         return;
00121     }
00122 
00123     bestd = 0;
00124     best = 0;
00125     bytedirsLength = lengthof(bytedirs);
00126     for (i = 0; i < bytedirsLength; i++) {
00127         const float d = DotProduct(dir, bytedirs[i]);
00128         if (d > bestd) {
00129             bestd = d;
00130             best = i;
00131         }
00132     }
00133     NET_WriteByte(buf, best);
00134 }
00135 
00136 
00141 void NET_vWriteFormat (struct dbuffer *buf, const char *format, va_list ap)
00142 {
00143     char typeID;
00144 
00145     while (*format) {
00146         typeID = *format++;
00147 
00148         switch (typeID) {
00149         case 'c':
00150             NET_WriteChar(buf, va_arg(ap, int));
00151 
00152             break;
00153         case 'b':
00154             NET_WriteByte(buf, va_arg(ap, int));
00155 
00156             break;
00157         case 's':
00158             NET_WriteShort(buf, va_arg(ap, int));
00159 
00160             break;
00161         case 'l':
00162             NET_WriteLong(buf, va_arg(ap, int));
00163 
00164             break;
00165         case 'p':
00166             NET_WritePos(buf, va_arg(ap, float *));
00167 
00168             break;
00169         case 'g':
00170             NET_WriteGPos(buf, va_arg(ap, byte *));
00171             break;
00172         case 'd':
00173             NET_WriteDir(buf, va_arg(ap, float *));
00174 
00175             break;
00176         case 'a':
00177             /* NOTE: float is promoted to double through ... */
00178             NET_WriteAngle(buf, va_arg(ap, double));
00179 
00180             break;
00181         case '!':
00182             break;
00183         case '&':
00184             NET_WriteString(buf, va_arg(ap, char *));
00185             break;
00186         case '*':
00187             {
00188                 int i, n;
00189                 byte *p;
00190 
00191                 n = va_arg(ap, int);
00192 
00193                 p = va_arg(ap, byte *);
00194                 NET_WriteShort(buf, n);
00195                 for (i = 0; i < n; i++)
00196                     NET_WriteByte(buf, *p++);
00197             }
00198             break;
00199         default:
00200             Com_Error(ERR_DROP, "WriteFormat: Unknown type!");
00201         }
00202     }
00203     /* Too many arguments for the given format; too few cause crash above */
00204     if (!ap)
00205         Com_Error(ERR_DROP, "WriteFormat: Too many arguments!");
00206 }
00207 
00211 void NET_WriteFormat (struct dbuffer *buf, const char *format, ...)
00212 {
00213     va_list ap;
00214     va_start(ap, format);
00215     NET_vWriteFormat(buf, format, ap);
00216     va_end(ap);
00217 }
00218 
00219 
00220 /* reading functions */
00221 
00225 int NET_ReadChar (struct dbuffer *buf)
00226 {
00227     char c;
00228     if (dbuffer_extract(buf, &c, 1) == 0)
00229         return -1;
00230     else
00231         return c;
00232 }
00233 
00239 int NET_ReadByte (struct dbuffer *buf)
00240 {
00241     unsigned char c;
00242     if (dbuffer_extract(buf, (char *)&c, 1) == 0)
00243         return -1;
00244     else
00245         return c;
00246 }
00247 
00248 int NET_ReadShort (struct dbuffer *buf)
00249 {
00250     unsigned short v;
00251     if (dbuffer_extract(buf, (char *)&v, 2) < 2)
00252         return -1;
00253 
00254     return LittleShort(v);
00255 }
00256 
00262 int NET_PeekShort (const struct dbuffer *buf)
00263 {
00264     uint16_t v;
00265     if (dbuffer_get(buf, (char *)&v, 2) < 2)
00266         return -1;
00267 
00268     return LittleShort(v);
00269 }
00270 
00271 int NET_ReadLong (struct dbuffer *buf)
00272 {
00273     unsigned int v;
00274     if (dbuffer_extract(buf, (char *)&v, 4) < 4)
00275         return -1;
00276 
00277     return LittleLong(v);
00278 }
00279 
00292 int NET_ReadString (struct dbuffer *buf, char *string, size_t length)
00293 {
00294     unsigned int l;
00295 
00296     l = 0;
00297     do {
00298         int c = NET_ReadByte(buf);
00299         if (c == -1 || c == 0)
00300             break;
00301         /* translate all format specs to avoid crash bugs */
00302         /* don't allow higher ascii values */
00303         if (c == '%' || c > 127)
00304             c = '.';
00305         string[l] = c;
00306         l++;
00307     } while (l < length - 1);
00308 
00309     string[l] = 0;
00310 
00311     return l;
00312 }
00313 
00317 int NET_ReadStringLine (struct dbuffer *buf, char *string, size_t length)
00318 {
00319     unsigned int l;
00320 
00321     l = 0;
00322     do {
00323         int c = NET_ReadByte(buf);
00324         if (c == -1 || c == 0 || c == '\n')
00325             break;
00326         /* translate all format specs to avoid crash bugs */
00327         /* don't allow higher ascii values */
00328         if (c == '%' || c > 127)
00329             c = '.';
00330         string[l] = c;
00331         l++;
00332     } while (l < length - 1);
00333 
00334     string[l] = 0;
00335 
00336     return l;
00337 }
00338 
00339 float NET_ReadCoord (struct dbuffer *buf)
00340 {
00341     return (float) NET_ReadLong(buf) * (1.0 / 32);
00342 }
00343 
00347 void NET_Read2Pos (struct dbuffer *buf, vec2_t pos)
00348 {
00349     pos[0] = NET_ReadLong(buf) / 32.;
00350     pos[1] = NET_ReadLong(buf) / 32.;
00351 }
00352 
00356 void NET_ReadPos (struct dbuffer *buf, vec3_t pos)
00357 {
00358     pos[0] = NET_ReadLong(buf) / 32.;
00359     pos[1] = NET_ReadLong(buf) / 32.;
00360     pos[2] = NET_ReadLong(buf) / 32.;
00361 }
00362 
00368 void NET_ReadGPos (struct dbuffer *buf, pos3_t pos)
00369 {
00370     pos[0] = NET_ReadByte(buf);
00371     pos[1] = NET_ReadByte(buf);
00372     pos[2] = NET_ReadByte(buf);
00373 }
00374 
00375 float NET_ReadAngle (struct dbuffer *buf)
00376 {
00377     return (float) NET_ReadChar(buf) * (360.0 / 256);
00378 }
00379 
00380 float NET_ReadAngle16 (struct dbuffer *buf)
00381 {
00382     short s;
00383 
00384     s = NET_ReadShort(buf);
00385     return (float) SHORT2ANGLE(s);
00386 }
00387 
00388 void NET_ReadData (struct dbuffer *buf, void *data, int len)
00389 {
00390     int i;
00391 
00392     for (i = 0; i < len; i++)
00393         ((byte *) data)[i] = NET_ReadByte(buf);
00394 }
00395 
00396 void NET_ReadDir (struct dbuffer *buf, vec3_t dir)
00397 {
00398     const int b = NET_ReadByte(buf);
00399     if (b >= lengthof(bytedirs))
00400         Com_Error(ERR_DROP, "NET_ReadDir: out of range");
00401     VectorCopy(bytedirs[b], dir);
00402 }
00403 
00404 
00411 void NET_vReadFormat (struct dbuffer *buf, const char *format, va_list ap)
00412 {
00413     while (*format) {
00414         const char typeID = *format++;
00415 
00416         switch (typeID) {
00417         case 'c':
00418             *va_arg(ap, int *) = NET_ReadChar(buf);
00419             break;
00420         case 'b':
00421             *va_arg(ap, int *) = NET_ReadByte(buf);
00422             break;
00423         case 's':
00424             *va_arg(ap, int *) = NET_ReadShort(buf);
00425             break;
00426         case 'l':
00427             *va_arg(ap, int *) = NET_ReadLong(buf);
00428             break;
00429         case 'p':
00430             NET_ReadPos(buf, *va_arg(ap, vec3_t *));
00431             break;
00432         case 'g':
00433             NET_ReadGPos(buf, *va_arg(ap, pos3_t *));
00434             break;
00435         case 'd':
00436             NET_ReadDir(buf, *va_arg(ap, vec3_t *));
00437             break;
00438         case 'a':
00439             *va_arg(ap, float *) = NET_ReadAngle(buf);
00440             break;
00441         case '!':
00442             format++;
00443             break;
00444         case '&': {
00445             char *str = va_arg(ap, char *);
00446             const size_t length = va_arg(ap, size_t);
00447             NET_ReadString(buf, str, length);
00448             break;
00449         }
00450         case '*':
00451             {
00452                 int i;
00453                 byte *p;
00454                 const int n = NET_ReadShort(buf);
00455 
00456                 *va_arg(ap, int *) = n;
00457                 p = va_arg(ap, byte *);
00458 
00459                 for (i = 0; i < n; i++)
00460                     *p++ = NET_ReadByte(buf);
00461             }
00462             break;
00463         default:
00464             Com_Error(ERR_DROP, "ReadFormat: Unknown type!");
00465         }
00466     }
00467     /* Too many arguments for the given format; too few cause crash above */
00468     if (!ap)
00469         Com_Error(ERR_DROP, "ReadFormat: Too many arguments!");
00470 }
00471 
00475 void NET_ReadFormat (struct dbuffer *buf, const char *format, ...)
00476 {
00477     va_list ap;
00478 
00479     va_start(ap, format);
00480     NET_vReadFormat(buf, format, ap);
00481     va_end(ap);
00482 }
00483 
00490 void NET_OOB_Printf (struct net_stream *s, const char *format, ...)
00491 {
00492     va_list argptr;
00493     char string[4096];
00494     const char cmd = (const char)clc_oob;
00495     int len;
00496 
00497     va_start(argptr, format);
00498     Q_vsnprintf(string, sizeof(string), format, argptr);
00499     va_end(argptr);
00500 
00501     len = LittleLong(strlen(string) + 1);
00502     NET_StreamEnqueue(s, (const char *)&len, 4);
00503     NET_StreamEnqueue(s, &cmd, 1);
00504     NET_StreamEnqueue(s, string, strlen(string));
00505 }
00506 
00512 void NET_WriteMsg (struct net_stream *s, struct dbuffer *buf)
00513 {
00514     char tmp[4096];
00515     int len = LittleLong(dbuffer_len(buf));
00516     NET_StreamEnqueue(s, (char *)&len, 4);
00517 
00518     while (dbuffer_len(buf)) {
00519         len = dbuffer_extract(buf, tmp, sizeof(tmp));
00520         NET_StreamEnqueue(s, tmp, len);
00521     }
00522 
00523     /* and now free the buffer */
00524     free_dbuffer(buf);
00525 }
00526 
00534 void NET_WriteConstMsg (struct net_stream *s, const struct dbuffer *buf)
00535 {
00536     char tmp[4096];
00537     int len = LittleLong(dbuffer_len(buf));
00538     int pos = 0;
00539     NET_StreamEnqueue(s, (char *)&len, 4);
00540 
00541     while (pos < dbuffer_len(buf)) {
00542         const int x = dbuffer_get_at(buf, pos, tmp, sizeof(tmp));
00543         assert(x > 0);
00544         NET_StreamEnqueue(s, tmp, x);
00545         pos += x;
00546     }
00547 }
00548 
00556 struct dbuffer *NET_ReadMsg (struct net_stream *s)
00557 {
00558     unsigned int v;
00559     unsigned int len;
00560     struct dbuffer *buf;
00561     char tmp[4096];
00562     if (NET_StreamPeek(s, (char *)&v, 4) < 4)
00563         return NULL;
00564 
00565     len = LittleLong(v);
00566     if (NET_StreamGetLength(s) < (4 + len))
00567         return NULL;
00568 
00569     NET_StreamDequeue(s, tmp, 4);
00570 
00571     buf = new_dbuffer();
00572     while (len > 0) {
00573         const int x = NET_StreamDequeue(s, tmp, min(len, 4096));
00574         dbuffer_add(buf, tmp, x);
00575         len -= x;
00576     }
00577 
00578     return buf;
00579 }
00580 
00581 void NET_VPrintf (struct dbuffer *buf, const char *format, va_list ap, char *str, size_t length)
00582 {
00583     const int len = Q_vsnprintf(str, length, format, ap);
00584     dbuffer_add(buf, str, len);
00585 }

Generated by  doxygen 1.6.2