/*
* Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the License);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace Tizen.Network.Bluetooth
{
///
/// The BluetoothSocket provides functions for managing connections to other devices and exchanging data.
///
public class BluetoothServerSocket : IDisposable
{
private event EventHandler _acceptStateChanged;
private Interop.Bluetooth.SocketConnectionStateChangedCallback _connectionStateChangedCallback;
internal int socketFd;
private bool disposed = false;
///
/// The AcceptStateChanged event is raised when the socket connection state is changed.
///
/// Thrown when the Bluetooth is not enabled
/// or when the register accpet state changed callback fails.
public event EventHandler AcceptStateChanged
{
add
{
if (_acceptStateChanged == null)
{
RegisterAcceptStateChangedEvent();
}
_acceptStateChanged += value;
}
remove
{
_acceptStateChanged -= value;
if (_acceptStateChanged == null)
{
UnregisterAcceptStateChangedEvent();
}
}
}
private void RegisterAcceptStateChangedEvent()
{
_connectionStateChangedCallback = (int result, BluetoothSocketState connectionState, ref SocketConnectionStruct socketConnection, IntPtr userData) =>
{
Log.Info(Globals.LogTag, "AcceptStateChanged cb is called");
if (_acceptStateChanged != null)
{
BluetoothSocket socket = new BluetoothSocket();
socket.connectedSocket = socketConnection.SocketFd;
GCHandle handle2 = (GCHandle) userData;
_acceptStateChanged(handle2.Target as BluetoothServerSocket, new AcceptStateChangedEventArgs((BluetoothError)result, connectionState, BluetoothUtils.ConvertStructToSocketConnection(socketConnection), socket));
}
};
GCHandle handle1 = GCHandle.Alloc(this);
IntPtr data = (IntPtr) handle1;
int ret = Interop.Bluetooth.SetConnectionStateChangedCallback(_connectionStateChangedCallback, data);
if (ret != (int)BluetoothError.None)
{
Log.Error(Globals.LogTag, "Failed to set accept state changed callback, Error - " + (BluetoothError)ret);
BluetoothErrorFactory.ThrowBluetoothException(ret);
}
}
private void UnregisterAcceptStateChangedEvent()
{
int ret = Interop.Bluetooth.UnsetSocketConnectionStateChangedCallback();
if (ret != (int)BluetoothError.None)
{
Log.Error(Globals.LogTag, "Failed to unset accept state changed callback, Error - " + (BluetoothError)ret);
BluetoothErrorFactory.ThrowBluetoothException(ret);
}
}
internal BluetoothServerSocket(int socketFd)
{
Log.Info (Globals.LogTag, "Constructing server socket");
this.socketFd = socketFd;
}
///
/// Starts listening on the passed RFCOMM socket and accepts connection requests.
///
///
/// The socket must be created with CreateServerSocket(). This API invokes the ConnectionStateChanged event.
///
/// Thrown when the Bluetooth is not enabled
/// or when the listen on socket procedure fails.
public void Listen()
{
int ret = Interop.Bluetooth.Listen(socketFd, 1);
if (ret != (int)BluetoothError.None)
{
Log.Error(Globals.LogTag, "Failed to accept connection, Error - " + (BluetoothError)ret);
BluetoothErrorFactory.ThrowBluetoothException(ret);
}
}
~BluetoothServerSocket()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
// Free managed objects.
}
//Free unmanaged objects
RemoveRegisteredEvents();
disposed = true;
}
private void RemoveRegisteredEvents()
{
//unregister all remaining events when this object is released.
if (_acceptStateChanged != null)
{
UnregisterAcceptStateChangedEvent();
}
}
}
}