File: image.c

package info (click to toggle)
crossfire 1.75.0-9
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 24,168 kB
  • sloc: ansic: 83,169; sh: 4,659; perl: 1,736; lex: 1,443; makefile: 1,199; python: 43
file content (187 lines) | stat: -rw-r--r-- 5,879 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/*
 * Crossfire -- cooperative multi-player graphical RPG and adventure game
 *
 * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
 * Copyright (c) 1992 Frank Tore Johansen
 *
 * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
 * welcome to redistribute it under certain conditions. For details, please
 * see COPYING and LICENSE.
 *
 * The authors can be reached via e-mail at <crossfire@metalforge.org>.
 */

/** \file
 * Image related communication
 *
 *  \date 2006-03-18
 *
 * This file deals with the image related communication to the
 * client.  I've located all the functions in this file - this
 * localizes it more, and means that we don't need to declare
 * things like all the structures as globals.
 */

#include "global.h"

#include <stdlib.h>
#include <string.h>

#include "image.h"
#include "newserver.h"
#include "shared/newclient.h"
#include "sproto.h"

/**
 * Client has requested pixmap that it somehow missed getting.
 * This will be called often if the client is
 * caching images.
 * @param buff data received from the client.
 * @param len length of buff, ignored.
 * @param ns socket to send data to.
 */
void send_face_cmd(char *buff, int len, socket_struct *ns) {
    long tmpnum;
    uint16_t faceid;

    if (len <= 0 || !buff) {
        LOG(llevDebug, "IP '%s' sent bogus send_face_cmd information\n", ns->host);
        return;
    }

    tmpnum = atoi(buff);
    faceid = tmpnum&0xffff;

    if (faceid != 0)
        esrv_send_face(ns, get_face_by_id(faceid), 1);
}

/**
 * Sends a face to a client if they are in pixmap mode,
 * nothing gets sent in bitmap mode.
 * If nocache is true (nonzero), ignore the cache setting from the client -
 * this is needed for the askface, in which we really do want to send the
 * face (and askface is the only place that should be setting it).  Otherwise,
 * we look at the facecache, and if set, send the image name.
 * @param ns socket to send the date to.
 * @param face face to send.
 * @param nocache if 1 then send a 'image2', else depending on client cache setting.
 */
void esrv_send_face(socket_struct *ns, const Face *face, int nocache) {
    SockList sl;
    int fallback;

    if (face == NULL) {
        LOG(llevError, "esrv_send_face NULL??\n");
        return;
    }

    SockList_Init(&sl);
    fallback = get_face_fallback(ns->faceset, face->number);

    if (facesets[fallback].faces[face->number].data == NULL) {
        LOG(llevError, "esrv_send_face: faces[%d].data == NULL\n", face->number);
        return;
    }

    if (ns->facecache && !nocache) {
        SockList_AddString(&sl, "face2 ");
        SockList_AddShort(&sl, face->number);
        SockList_AddChar(&sl, fallback);
        SockList_AddInt(&sl, facesets[fallback].faces[face->number].checksum);
        SockList_AddString(&sl, face->name);
        Send_With_Handling(ns, &sl);
    } else {
        SockList_AddString(&sl, "image2 ");
        SockList_AddInt(&sl, face->number);
        SockList_AddChar(&sl, fallback);
        SockList_AddInt(&sl, facesets[fallback].faces[face->number].datalen);
        SockList_AddData(&sl, facesets[fallback].faces[face->number].data, facesets[fallback].faces[face->number].datalen);
        Send_With_Handling(ns, &sl);
    }
    ns->faces_sent[face->number] |= NS_FACESENT_FACE;
    SockList_Term(&sl);
}

/**
 * Sends the number of images, checksum of the face file,
 * and the image_info file information.  See the doc/Developers/protocol
 * if you want further detail.
 * @param ns socket to send data to.
 */
void send_image_info(socket_struct *ns) {
    SockList sl;
    int i;

    SockList_Init(&sl);
    SockList_AddPrintf(&sl, "replyinfo image_info\n%d\n%d\n", get_faces_count()-1, bmaps_checksum);
    for (i = 0; i < MAX_FACE_SETS; i++) {
        if (facesets[i].prefix) {
            SockList_AddPrintf(&sl, "%d:%s:%s:%d:%s:%s:%s",
                     i, facesets[i].prefix, facesets[i].fullname,
                     facesets[i].fallback, facesets[i].size,
                     facesets[i].extension, facesets[i].comment);
        }
    }
    Send_With_Handling(ns, &sl);
    SockList_Term(&sl);
}

/**
 * Sends requested face information.
 * \param ns socket to send to
 * \param params contains first and last index of face
 *
 * For each image in [start..stop] sends
 *  - checksum
 *  - name
 */
void send_image_sums(socket_struct *ns, char *params) {
    unsigned int start, stop;
    unsigned short i;
    char *cp;
    SockList sl;

    SockList_Init(&sl);

    start = atoi(params);
    for (cp = params; *cp != '\0'; cp++)
        if (*cp == ' ')
            break;

    stop = atoi(cp);
    if (stop < start
    || *cp == '\0'
    || (stop-start) > 1000
    || stop >= get_faces_count()) {
        SockList_AddPrintf(&sl, "replyinfo image_sums %d %d", start, stop);
        Send_With_Handling(ns, &sl);
        SockList_Term(&sl);
        return;
    }
    SockList_AddPrintf(&sl, "replyinfo image_sums %d %d ", start, stop);

    for (i = start; i <= stop; i++) {
        int faceset;
        const Face *face = get_face_by_index(i);

        if (SockList_Avail(&sl) < 2+4+1+1+strlen(face->name)+1) {
            LOG(llevError, "send_image_sums: buffer overflow, rejecting range %d..%d\n", start, stop);
            SockList_Reset(&sl);
            SockList_AddPrintf(&sl, "replyinfo image_sums %d %d", start, stop);
            Send_With_Handling(ns, &sl);
            SockList_Term(&sl);
            return;
        }

        SockList_AddShort(&sl, i);
        ns->faces_sent[face->number] |= NS_FACESENT_FACE;

        faceset = get_face_fallback(ns->faceset, i);
        SockList_AddInt(&sl, facesets[faceset].faces[i].checksum);
        SockList_AddChar(&sl, faceset);
        SockList_AddLen8Data(&sl, face->name, strlen(face->name)+1);
    }
    Send_With_Handling(ns, &sl);
    SockList_Term(&sl);
}