tport_stub_sigcomp.c 6.73 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/su_string.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 && su_casematch(comp, tport_sigcomp_name))
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
/** 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
143
    self && comp &&
144 145 146
    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
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;
}


172
/** Assign a SigComp compartment (to a possibly connected tport).
173 174 175 176 177 178 179
 *
 * @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
  if (!vsc)
    return 0;

183
  if (tport_is_connection_oriented(self) &&
184
      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
/** 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);
220

221 222 223
  return 0;
}

224 225 226
int
tport_sigcomp_accept(tport_t *self,
		     struct sigcomp_compartment *cc,
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
		     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
int tport_recv_comp_dgram(tport_t const *self,
264
			  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
ssize_t tport_send_comp(tport_t const *self,
281 282
			msg_t *msg,
			msg_iovec_t iov[],
283 284 285
			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);
}