File: manager.c

package info (click to toggle)
camserv 0.42-9
  • links: PTS
  • area: main
  • in suites: woody
  • size: 1,884 kB
  • ctags: 1,123
  • sloc: ansic: 19,694; sh: 7,454; makefile: 206
file content (213 lines) | stat: -rw-r--r-- 6,273 bytes parent folder | download
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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/*  camserv - An internet streaming picture application
 *
 *  Copyright (C) 1999  Jon Travis (jon@dsndata.com)
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include <stdio.h>
#include <stdlib.h>
#include "list.h"
#include "manager.h"

typedef struct picture_bin_st {

  char *picture_data;       /* Picture information */
  size_t picture_size;      
  int picture_id;
  int nClients;             /* # of clients using the bin */
} Picture_Bin;

/*
 * The manager routines take care of how many data bins we are using, and
 * who is using them.  This keeps the amount of memory low, if multiple
 * clients are waiting for the same picture.
 */

static list_t *Manager_BinList = NULL;
static int BinList_Size = 0;
static int Current_Picture_Id = 0;

/*
 * picture_bin_new:  Create a new picture bin to store a picture and
 *                   the users connected with it.  
 *
 * Return values:    Returns NULL on failure, else a valid pointer to
 *                   a fresh chunk of memory containing the picture bin
 */

static
Picture_Bin *picture_bin_new( ){
  Picture_Bin *res;

  if( (res = malloc( sizeof( *res ))) == NULL ){
    return NULL;
  }

  res->picture_data = NULL;
  res->picture_size = 0;
  res->nClients = 0;
  res->picture_id = 0;
  return res;
}

static
void picture_bin_dest( Picture_Bin *bin ){
  if( bin->picture_data != NULL )
    free( bin->picture_data );

  free( bin );
}

/*
 * manager_new_picture:  
 * Tell the manager routines to manage a new picture.  This
 * routine will attempt to allocate space to store the 
 * picture within the list, in addition to cleaning out old
 * pictures with no connected clients. 
 *
 * Arguments: picture_data = Caller-allocated memory containing
 *                           the picture to send to the client. 
 *                           The caller should noc free the 
 *                           picture data after passing in here, it
 *                           will be freed upon bin cleanup.
 *
 *            pic_size     = Amount of data in picture_data
 * 
 *            max_clients  = Max # of clients to support per picture
 *
 * Return values:  Returns -1 if the routine failed to manage
 *                 the picture (Malloc failure), else 0
 */

int
manager_new_picture( char *picture_data, size_t pic_size, int max_clients ){
  Picture_Bin *new_bin;
  lnode_t *binlist_node, *node_next;

  if( (new_bin = picture_bin_new( max_clients )) == NULL ){
    return -1;
  }

  new_bin->picture_data = picture_data;
  new_bin->picture_size = pic_size;
  new_bin->picture_id = Current_Picture_Id++;

  if( (binlist_node = lnode_create( new_bin )) == NULL ){
    fprintf( stderr, "Manager; Couldn't allocate lnode!\n");
    picture_bin_dest( new_bin );
    return -1;
  }

  if( Manager_BinList == NULL ) {
    if( (Manager_BinList = list_create( -1 )) == NULL ){
      fprintf( stderr, "Manager:  Couldn't allocate linked list!\n");
      lnode_destroy( binlist_node );
      picture_bin_dest( new_bin );
      return -1;
    }
  }

  list_prepend( Manager_BinList, binlist_node );
  BinList_Size++;

  binlist_node = list_next( Manager_BinList,
			    binlist_node ); /* To avoid the new one */
  for( ;
       binlist_node != NULL; 
       binlist_node = node_next )
  {
    Picture_Bin *node_data;
    
    node_data = binlist_node->data;
    node_next = list_next( Manager_BinList, binlist_node );
    
    /* If the bin doesn't have any clients, just delete it */
    
    if( node_data->nClients == 0 ){
      list_delete( Manager_BinList, binlist_node );
      picture_bin_dest( node_data );
      lnode_destroy( binlist_node );
      BinList_Size--;
    } 
  }      
  return 0;
}


/*
 * manager_new_client:  Add a client to the list of managed
 *                      clients & picture bins.  This routine will
 *                      figure out the most up-to-date picture to 
 *                      send the client, and return information that
 *                      the client will need to know to send the
 *                      picture, and free themselves up after they
 *                      have sent it.
 *
 * Arguments:
 *                      pic_data = Storage place to put the pointer to the
 *                                 picture data for the client to use
 *          
 *                      pic_size = Storage place to put the picture size
 *
 *                      pic_id   = Storage place to put the picture ID
 *
 * Return values:       Returns NULL on failure (unknown), else a valid
 *                      pointer which must be passed to manager_dest_client
 *                      when the client is done using the picture.
 */

void *manager_new_client( char **pic_data, size_t *pic_size, 
			  int *pic_id )
{
  lnode_t *binlist_head_node;
  Picture_Bin *pic_bin;

  if( Manager_BinList == NULL ) 
    return NULL;

  binlist_head_node = list_first( Manager_BinList );
  if( binlist_head_node == NULL ){
    return NULL;
  }
  
  pic_bin = binlist_head_node->data;

  *pic_data = pic_bin->picture_data;
  *pic_size = pic_bin->picture_size;
  *pic_id   = pic_bin->picture_id;
  pic_bin->nClients++;

  return binlist_head_node;
}

/*
 * manager_dest_client:  Remove a client from using a managed bin.
 *                      
 * Arguments:            reset_data = Data returned from manager_new_client
 *
 * Return values:  Returns 0 on success, -1 on failure.
 */

int manager_dest_client( void *reset_data ){
  Picture_Bin *pic_bin;
  lnode_t *binlist_node;

  binlist_node = reset_data;
  pic_bin = binlist_node->data;
  
  pic_bin->nClients--;
  return 0;
}