summaryrefslogtreecommitdiff
path: root/ace/SOCK_SEQPACK_Association.cpp
blob: f0a1ec6c392e4850ec4234631f2a0d23ae974042 (plain)
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
// SOCK_SEQPACK_Association.cpp

#include /**/ "ace/SOCK_SEQPACK_Association.h"
#include /**/ "ace/Auto_Ptr.h"
#include /**/ "ace/Log_Msg.h"

#if defined (ACE_LACKS_INLINE_FUNCTIONS)
#include /**/ "ace/SOCK_SEQPACK_Association.i"
#endif

ACE_RCSID(ace, SOCK_SEQPACK_Association, "$Id$")

ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_SEQPACK_Association)

void
ACE_SOCK_SEQPACK_Association::dump (void) const
{
  ACE_TRACE ("ACE_SOCK_SEQPACK_Association::dump");
}

int
ACE_SOCK_SEQPACK_Association::close (void)
{
#if defined (ACE_WIN32)
  // We need the following call to make things work correctly on
  // Win32, which requires use to do a <close_writer> before doing the
  // close in order to avoid losing data.  Note that we don't need to
  // do this on UNIX since it doesn't have this "feature".  Moreover,
  // this will cause subtle problems on UNIX due to the way that
  // fork() works.
  this->close_writer ();
#endif /* ACE_WIN32 */
  // Close down the socket.
  return ACE_SOCK::close ();
}

int
ACE_SOCK_SEQPACK_Association::get_local_addrs (ACE_INET_Addr *addrs, size_t &size) const
{
  ACE_TRACE ("ACE_SOCK_SEQPACK_Association::get_local_addrs");

  /*
    We will be calling ACE_OS::getsockname, which accepts (and
    potentially modifies) two reference parameters:

    1.  a sockaddr_in* that points to a buffer
    2.  an int* that points to the size of this buffer

    The OpenSS7 implementation of SCTP copies an array of ipv4
    sockaddr_in into the buffer.  Then, if the size of the buffer is
    greater than the size used, the size parameter is reduced
    accordingly.

  */

  // The array of sockaddr_in will be stored in an ACE_Auto_Array_Ptr,
  // which causes dynamically-allocated memory to be released as soon
  // as the ACE_Auto_Array_Ptr goes out of scope.
  ACE_Auto_Array_Ptr<sockaddr_in> addr_structs;

  // Allocate memory for this array.  Return -1 if the memory cannot
  // be allocated.  (This activity requires a temporary variable---a
  // bare sockaddr_in* --- because ACE_NEW_RETURN cannot act directory on
  // an ACE_Auto_Array_Ptr.)
  {
    sockaddr_in *addr_structs_bootstrap = 0;
    ACE_NEW_RETURN(addr_structs_bootstrap,
                   sockaddr_in[size],
                   -1);
    addr_structs.reset(addr_structs_bootstrap);
  }

  // Physical size of this array is its logical size multiplied by
  // the physical size of one of its elements.
  int physical_size = size * sizeof(sockaddr_in);

  /* Clear the array */
  ACE_OS::memset(addr_structs.get(),
                 0,
                 physical_size);

  /* Populate the array with real values from the getsockname system
     call.  The variables addr_structs and phycisal_size are
     modified. */
  if (ACE_OS::getsockname (this->get_handle (),
                           ACE_reinterpret_cast (sockaddr *,
                                                 addr_structs.get()),
                           &physical_size) == -1)
    return -1;

  /* Calculate the NEW physical size of the array */
  size = physical_size / sizeof (sockaddr_in);

  /* Copy each sockaddr_in to the address structure of an ACE_Addr from
     the passed-in array */
  for (size_t i = 0; i < size; ++i) {

    addrs[i].set_addr(&(addr_structs[i]), sizeof(sockaddr_in));
    addrs[i].set_type(addr_structs[i].sin_family);
    addrs[i].set_size(sizeof(sockaddr_in));
  }

  return 0;
}

int
ACE_SOCK_SEQPACK_Association::get_remote_addrs (ACE_INET_Addr *addrs, size_t &size) const
{
  ACE_TRACE ("ACE_SOCK_SEQPACK_Association::get_remote_addrs");

  /*
    We will be calling ACE_OS::getpeername, which accepts (and
    potentially modifies) two reference parameters:

    1.  a sockaddr_in* that points to a buffer
    2.  an int* that points to the size of this buffer

    The OpenSS7 implementation of SCTP copies an array of ipv4
    sockaddr_in into the buffer.  Then, if the size of the buffer is
    greater than the size used, the size parameter is reduced
    accordingly.

  */

  // The array of sockaddr_in will be stored in an ACE_Auto_Array_Ptr,
  // which causes dynamically-allocated memory to be released as soon
  // as the ACE_Auto_Array_Ptr goes out of scope.
  ACE_Auto_Array_Ptr<sockaddr_in> addr_structs;

  // Allocate memory for this array.  Return -1 if the memory cannot
  // be allocated.  (This activity requires a temporary variable---a
  // bare sockaddr_in* --- because ACE_NEW_RETURN cannot act directory on
  // an ACE_Auto_Array_Ptr.)
  {
    sockaddr_in *addr_structs_bootstrap = 0;
    ACE_NEW_RETURN(addr_structs_bootstrap,
                   sockaddr_in[size],
                   -1);
    addr_structs.reset(addr_structs_bootstrap);
  }

  // Physical size of this array is its logical size multiplied by
  // the physical size of one of its elements.
  int physical_size = size * sizeof(sockaddr_in);

  /* Clear the array */
  ACE_OS::memset(addr_structs.get(),
                 0,
                 physical_size);

  /* Populate the array with real values from the getpeername system
     call.  The variables addr_structs and phycisal_size are
     modified. */
  if (ACE_OS::getpeername (this->get_handle (),
                           ACE_reinterpret_cast (sockaddr *,
                                                 addr_structs.get()),
                           &physical_size) == -1)
    return -1;

  /* Calculate the NEW physical size of the array */
  size = physical_size / sizeof (sockaddr_in);

  /* Copy each sockaddr_in to the address structure of an ACE_Addr from
     the passed-in array */
  for (size_t i = 0; i < size; ++i) {

    addrs[i].set_addr(&(addr_structs[i]), sizeof(sockaddr_in));
    addrs[i].set_type(addr_structs[i].sin_family);
    addrs[i].set_size(sizeof(sockaddr_in));
  }

  return 0;
}

#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
template class ACE_Auto_Array_Ptr<sockaddr_in>;
template class ACE_Auto_Basic_Array_Ptr<sockaddr_in>;
#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
#pragma instantiate ACE_Auto_Array_Ptr<sockaddr_in>
#pragma instantiate ACE_Auto_Basic_Array_Ptr<sockaddr_in>
#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */