~ubuntu-branches/debian/experimental/kopete/experimental

« back to all changes in this revision

Viewing changes to protocols/jabber/libjingle/talk/base/transformadapter.cc

  • Committer: Package Import Robot
  • Author(s): Maximiliano Curia
  • Date: 2015-02-24 11:32:57 UTC
  • mfrom: (1.1.41 vivid)
  • Revision ID: package-import@ubuntu.com-20150224113257-gnupg4v7lzz18ij0
Tags: 4:14.12.2-1
* New upstream release (14.12.2).
* Bump Standards-Version to 3.9.6, no changes needed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * libjingle
 
3
 * Copyright 2004--2005, Google Inc.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions are met:
 
7
 *
 
8
 *  1. Redistributions of source code must retain the above copyright notice,
 
9
 *     this list of conditions and the following disclaimer.
 
10
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 
11
 *     this list of conditions and the following disclaimer in the documentation
 
12
 *     and/or other materials provided with the distribution.
 
13
 *  3. The name of the author may not be used to endorse or promote products
 
14
 *     derived from this software without specific prior written permission.
 
15
 *
 
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 
17
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 
18
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 
19
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
20
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
21
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 
22
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 
23
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 
24
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 
25
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
26
 */
 
27
 
 
28
#include "talk/base/transformadapter.h"
 
29
 
 
30
#include <cstring>
 
31
 
 
32
#include "talk/base/common.h"
 
33
 
 
34
namespace talk_base {
 
35
 
 
36
///////////////////////////////////////////////////////////////////////////////
 
37
 
 
38
TransformAdapter::TransformAdapter(StreamInterface * stream,
 
39
                                   TransformInterface * transform,
 
40
                                   bool direction_read)
 
41
    : StreamAdapterInterface(stream), transform_(transform),
 
42
      direction_read_(direction_read), state_(ST_PROCESSING), len_(0) {
 
43
}
 
44
 
 
45
TransformAdapter::~TransformAdapter() {
 
46
  TransformAdapter::Close();
 
47
  delete transform_;
 
48
}
 
49
 
 
50
StreamResult
 
51
TransformAdapter::Read(void * buffer, size_t buffer_len,
 
52
                       size_t * read, int * error) {
 
53
  if (!direction_read_)
 
54
    return SR_EOS;
 
55
 
 
56
  while (state_ != ST_ERROR) {
 
57
    if (state_ == ST_COMPLETE)
 
58
      return SR_EOS;
 
59
 
 
60
    // Buffer more data
 
61
    if ((state_ == ST_PROCESSING) && (len_ < sizeof(buffer_))) {
 
62
      size_t subread;
 
63
      StreamResult result = StreamAdapterInterface::Read(
 
64
                              buffer_ + len_,
 
65
                              sizeof(buffer_) - len_,
 
66
                              &subread,
 
67
                              &error_);
 
68
      if (result == SR_BLOCK) {
 
69
        return SR_BLOCK;
 
70
      } else if (result == SR_ERROR) {
 
71
        state_ = ST_ERROR;
 
72
        break;
 
73
      } else if (result == SR_EOS) {
 
74
        state_ = ST_FLUSHING;
 
75
      } else {
 
76
        len_ += subread;
 
77
      }
 
78
    }
 
79
 
 
80
    // Process buffered data
 
81
    size_t in_len = len_;
 
82
    size_t out_len = buffer_len;
 
83
    StreamResult result = transform_->Transform(buffer_, &in_len,
 
84
                                                buffer, &out_len,
 
85
                                                (state_ == ST_FLUSHING));
 
86
    ASSERT(result != SR_BLOCK);
 
87
    if (result == SR_EOS) {
 
88
      // Note: Don't signal SR_EOS this iteration, unless out_len is zero
 
89
      state_ = ST_COMPLETE;
 
90
    } else if (result == SR_ERROR) {
 
91
      state_ = ST_ERROR;
 
92
      error_ = -1; // TODO: propagate error
 
93
      break;
 
94
    } else if ((out_len == 0) && (state_ == ST_FLUSHING)) {
 
95
      // If there is no output AND no more input, then something is wrong
 
96
      state_ = ST_ERROR;
 
97
      error_ = -1; // TODO: better error code?
 
98
      break;
 
99
    }
 
100
 
 
101
    len_ -= in_len;
 
102
    if (len_ > 0)
 
103
      memmove(buffer_, buffer_ + in_len, len_);
 
104
 
 
105
    if (out_len == 0)
 
106
      continue;
 
107
 
 
108
    if (read)
 
109
      *read = out_len;
 
110
    return SR_SUCCESS;
 
111
  }
 
112
 
 
113
  if (error)
 
114
    *error = error_;
 
115
  return SR_ERROR;
 
116
}
 
117
 
 
118
StreamResult
 
119
TransformAdapter::Write(const void * data, size_t data_len,
 
120
                        size_t * written, int * error) {
 
121
  if (direction_read_)
 
122
    return SR_EOS;
 
123
 
 
124
  size_t bytes_written = 0;
 
125
  while (state_ != ST_ERROR) {
 
126
    if (state_ == ST_COMPLETE)
 
127
      return SR_EOS;
 
128
 
 
129
    if (len_ < sizeof(buffer_)) {
 
130
      // Process buffered data
 
131
      size_t in_len = data_len;
 
132
      size_t out_len = sizeof(buffer_) - len_;
 
133
      StreamResult result = transform_->Transform(data, &in_len,
 
134
                                                  buffer_ + len_, &out_len,
 
135
                                                  (state_ == ST_FLUSHING));
 
136
 
 
137
      ASSERT(result != SR_BLOCK);
 
138
      if (result == SR_EOS) {
 
139
        // Note: Don't signal SR_EOS this iteration, unless no data written
 
140
        state_ = ST_COMPLETE;
 
141
      } else if (result == SR_ERROR) {
 
142
        ASSERT(false); // When this happens, think about what should be done
 
143
        state_ = ST_ERROR;
 
144
        error_ = -1; // TODO: propagate error
 
145
        break;
 
146
      }
 
147
 
 
148
      len_ = out_len;
 
149
      bytes_written = in_len;
 
150
    }
 
151
 
 
152
    size_t pos = 0;
 
153
    while (pos < len_) {
 
154
      size_t subwritten;
 
155
      StreamResult result = StreamAdapterInterface::Write(buffer_ + pos,
 
156
                                                          len_ - pos,
 
157
                                                          &subwritten,
 
158
                                                          &error_);
 
159
      if (result == SR_BLOCK) {
 
160
        ASSERT(false); // TODO: we should handle this
 
161
        return SR_BLOCK;
 
162
      } else if (result == SR_ERROR) {
 
163
        state_ = ST_ERROR;
 
164
        break;
 
165
      } else if (result == SR_EOS) {
 
166
        state_ = ST_COMPLETE;
 
167
        break;
 
168
      }
 
169
 
 
170
      pos += subwritten;
 
171
    }
 
172
 
 
173
    len_ -= pos;
 
174
    if (len_ > 0)
 
175
      memmove(buffer_, buffer_ + pos, len_);
 
176
 
 
177
    if (bytes_written == 0)
 
178
      continue;
 
179
 
 
180
    if (written)
 
181
      *written = bytes_written;
 
182
    return SR_SUCCESS;
 
183
  }
 
184
 
 
185
  if (error)
 
186
    *error = error_;
 
187
  return SR_ERROR;
 
188
}
 
189
 
 
190
void
 
191
TransformAdapter::Close() {
 
192
  if (!direction_read_ && (state_ == ST_PROCESSING)) {
 
193
    state_ = ST_FLUSHING;
 
194
    do {
 
195
      Write(0, 0, NULL, NULL);
 
196
    } while (state_ == ST_FLUSHING);
 
197
  }
 
198
  state_ = ST_COMPLETE;
 
199
  StreamAdapterInterface::Close();
 
200
}
 
201
 
 
202
} // namespace talk_base