tport_stub_sigcomp.c 6.76 KB
Newer Older
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
/*
 * This file is part of the Sofia-SIP package
 *
 * Copyright (C) 2006 Nokia Corporation.
 *
 * Contact: Pekka Pessi <pekka.pessi@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

/**@CFILE tport_stub_sigcomp.c Stub interface for SigComp
 *
 * @author Pekka Pessi <Pekka.Pessi@nokia.com>
 *
 * @date Created: Fri Mar 31 12:31:36 EEST 2006
 */

#include "config.h"

#include "tport_internal.h"

36
#include <string.h>
37
#include <sofia-sip/string0.h>
38

39 40 41 42 43 44 45 46 47 48 49 50
tport_comp_vtable_t const *tport_comp_vtable = NULL;

int tport_plug_in_compress(tport_comp_vtable_t const *vsc)
{
  return -1;
}

char const tport_sigcomp_name[] = "sigcomp";

/** Canonize compression string */
char const *tport_canonize_comp(char const *comp)
{
51
  if (tport_comp_vtable && comp && strcasecmp(comp, tport_sigcomp_name) == 0)
52 53 54 55
    return tport_sigcomp_name;
  return NULL;
}

56 57 58
int tport_init_compressor(tport_t *tp,
			  char const *comp_name,
			  tagi_t const *tags)
59 60
{
  tport_comp_vtable_t const *vsc = tport_comp_vtable;
61 62
  tport_master_t *mr = tp ? tp->tp_master : NULL;
  tport_compressor_t *tcc;
63

64 65 66 67
  if (vsc == NULL)
    return -1;
  if (mr == NULL)
    return -1;
68

69 70 71
  if (tp->tp_comp)
    return 0;

72 73 74 75
  comp_name = tport_canonize_comp(comp_name);
  if (comp_name == NULL)
    return 0;

76 77 78 79 80 81 82 83 84 85 86
  tcc = su_zalloc(tp->tp_home, vsc->vsc_sizeof_context);

  if (tcc == NULL)
    return -1;

  if (vsc->vsc_init_comp(mr->mr_stack, tp, tcc, comp_name, tags) < 0) {
    vsc->vsc_deinit_comp(mr->mr_stack, tp, tcc);
    return -1;
  }

  tp->tp_comp = tcc;
87

88
  return 0;
89 90
}

91
void tport_deinit_compressor(tport_t *tp)
92 93
{
  tport_comp_vtable_t const *vsc = tport_comp_vtable;
94
  tport_master_t *mr = tp ? tp->tp_master : NULL;
95

96 97 98 99
  if (vsc && mr && tp->tp_comp) {
    vsc->vsc_deinit_comp(mr->mr_stack, tp, tp->tp_comp);
    su_free(tp->tp_home, tp->tp_comp), tp->tp_comp = NULL;
  }
100 101
}

102

103 104 105 106 107
char const *tport_comp_name(tport_primary_t *pri,
			    char const *name,
			    tagi_t const *tags)
{
  tport_comp_vtable_t const *vsc = tport_comp_vtable;
108
  tport_compressor_t const *comp = pri->pri_master->mr_master->tp_comp;
109 110 111 112 113 114 115

  if (vsc)
    return vsc->vsc_comp_name(comp, name, tags);

  return NULL;
}

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
/** Check if transport can receive compressed messages */
int tport_can_recv_sigcomp(tport_t const *self)
{
  tport_comp_vtable_t const *vsc = tport_comp_vtable;

  if (vsc)
    return vsc->vsc_can_recv_comp(self->tp_comp);

  return 0;
}

/** Check if transport can send compressed messages */
int tport_can_send_sigcomp(tport_t const *self)
{
  tport_comp_vtable_t const *vsc = tport_comp_vtable;

  if (vsc)
    return vsc->vsc_can_send_comp(self->tp_comp);

  return 0;
}

/** Check if transport supports named compression */
int tport_has_compression(tport_t const *self, char const *comp)
{
  return
    self && comp && 
    self->tp_name->tpn_comp == tport_canonize_comp(comp);
}

147
/** Set the compression protocol as @a comp. */
148 149 150 151 152 153 154 155 156 157
int tport_set_compression(tport_t *self, char const *comp)
{
  tport_comp_vtable_t const *vsc = tport_comp_vtable;

  if (vsc)
    return vsc->vsc_set_comp_name(self, self->tp_comp, comp);

  return (self == NULL || comp) ? -1 : 0;
}

158
/** Set SigComp options. */
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
int tport_sigcomp_option(tport_t const *self,
			 struct sigcomp_compartment *cc,
			 char const *option)
{
  tport_comp_vtable_t const *vsc = tport_comp_vtable;

  if (vsc)
    return vsc->vsc_sigcomp_option(self, cc, option);

  return -1;
}


/** Assign a SigComp compartment (to a possibly connected tport). 
 *
 * @related tport_s
 */
int tport_sigcomp_assign(tport_t *self, struct sigcomp_compartment *cc)
{
  tport_comp_vtable_t const *vsc = tport_comp_vtable;

180 181 182 183 184
  if (!vsc)
    return 0;

  if (tport_is_connection_oriented(self) && 
      tport_is_secondary(self) &&
185
      self->tp_socket != INVALID_SOCKET) {
186 187
    return vsc->vsc_set_compartment(self, self->tp_comp, cc);
  }
188 189 190 191

  return 0;
}

192 193 194 195 196 197
struct sigcomp_compartment *
tport_sigcomp_assign_if_needed(tport_t *self,
			       struct sigcomp_compartment *cc)
{
  tport_comp_vtable_t const *vsc = tport_comp_vtable;

198 199 200 201 202 203 204 205 206 207 208 209
  if (!vsc)
    return NULL;

  if (!self->tp_name->tpn_comp)
    return NULL;

  if (cc) {
    tport_sigcomp_assign(self, cc);
    return cc;
  }

  return vsc->vsc_get_compartment(self, self->tp_comp);
210 211 212
}			   


213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
/** Test if tport has a SigComp compartment assigned to it. */
int tport_has_sigcomp_assigned(tport_t const *self)
{
  tport_comp_vtable_t const *vsc = tport_comp_vtable;

  if (vsc && self)
    return vsc->vsc_has_sigcomp_assigned(self->tp_comp);
    
  return 0;
}

int 
tport_sigcomp_accept(tport_t *self, 
		     struct sigcomp_compartment *cc, 
		     msg_t *msg)
{
  tport_comp_vtable_t const *vsc = tport_comp_vtable;

  if (self == NULL)
    return su_seterrno(EFAULT);

  if (vsc)
    return vsc->vsc_sigcomp_accept(self, self->tp_comp, cc, msg);

  return 0;
}

/* Internal API */

242 243
/** This function is called when the application message is still incomplete
    but a complete SigComp message could have been received */
244
void tport_sigcomp_accept_incomplete(tport_t *self, msg_t *msg)
245 246 247
{
  tport_comp_vtable_t const *vsc = tport_comp_vtable;

248 249
  if (vsc && self->tp_comp)
    vsc->vsc_accept_incomplete(self, self->tp_comp, msg);
250 251 252 253 254 255 256 257 258 259 260 261 262
}

struct sigcomp_udvm **tport_get_udvm_slot(tport_t *self)
{
  tport_comp_vtable_t const *vsc = tport_comp_vtable;

  if (vsc && self)
    return vsc->vsc_get_udvm_slot(self);

  return NULL;
}

/** Receive data from datagram using SigComp. */
263 264
int tport_recv_comp_dgram(tport_t const *self, 
			  tport_compressor_t *sc,
265 266 267
			  msg_t **in_out_msg,
			  su_sockaddr_t *from,
			  socklen_t fromlen)
268 269 270 271
{
  tport_comp_vtable_t const *vsc = tport_comp_vtable;

  if (vsc)
272
    return vsc->vsc_recv_comp(self, sc, in_out_msg, from, fromlen);
273

274
  msg_destroy(*in_out_msg), *in_out_msg = NULL;
275

276
  return su_seterrno(EBADMSG);     
277 278 279
}


280 281 282 283 284 285
ssize_t tport_send_comp(tport_t const *self,
			msg_t *msg, 
			msg_iovec_t iov[], 
			size_t iovused,
			struct sigcomp_compartment *cc,
			tport_compressor_t *comp)
286 287 288 289 290 291 292 293 294
{
  tport_comp_vtable_t const *vsc = tport_comp_vtable;

  if (vsc)
    vsc->vsc_send_comp(self, msg, iov, iovused, cc, comp);

  msg_addrinfo(msg)->ai_flags &= ~TP_AI_COMPRESSED;
  return self->tp_pri->pri_vtable->vtp_send(self, msg, iov, iovused);
}