これらのライブラリはノーサポート扱いであり、基本的に製品に含めることができません。製品に利用する場合は弊社窓口までご相談ください。
デバッグ用途に限定して、無線通信モジュールを利用したソケット通信などのネットワーク接続に関するライブラリを用意しています。
機能 |
ライブラリ名 |
名前空間 |
説明 |
---|---|---|---|
ソケット通信 |
SOCKET |
|
ソケットを通じてリモートホストとのデータ送受信などを実現するライブラリです。 |
SSL 通信 |
SSL |
|
SSL による秘匿通信を補助するライブラリです。 |
HTTP 通信 |
HTTP |
|
HTTP による通信を行うライブラリです。 |
HTTP ライブラリは内部でソケット通信を行いますが、アプリケーションによる socket API の操作が HTTP ライブラリのソケット通信に影響を与えることはありません。
たとえば、HTTP ライブラリを使用している状態で nn::socket::Initialize()
や nn::socket::Finalize()
を呼び出しても、HTTP ライブラリの処理に影響はありません。
6.1. ソケット通信
SOCKET(ソケット通信)ライブラリは、アドレスおよびポート番号と結び付けられたソケットを介してリモートホストとの通信を行うライブラリです。ソケット通信は、ローカル(マシン)とリモートホストとの間のデータの送受信やリモートホストの接続待ち受け、ローカルからリモートホストへの接続といった低位の通信機能を提供します。
6.1.1. 初期化
SOCKET ライブラリの初期化は nn::socket::Initialize()
の呼び出しで行われます。
size_t nn::socket::GetRequiredMemorySize(size_t bufferSizeForSockets, s32 maxSessions); nn::Result nn::socket::Initialize(uptr bufferAddress, size_t bufferSize, s32 bufferSizeForSockets, s32 maxSessions);
bufferAddress
と bufferSize
には、ライブラリが使用するワークメモリの先頭アドレスとそのサイズを指定します。ワークメモリは先頭アドレスのアライメントが nn::socket::BUFFER_ALIGNMENT
( 4096 Byte ) で、デバイスメモリ以外から確保 しなければなりません。ワークメモリに必要なサイズは、ソケット全体で確保する送受信バッファのサイズ(bufferSizeForSockets
)と最大セッション数(maxSessions
)を引数に、nn::socket::GetRequiredMemorySize()
を呼び出して取得することができます。このとき指定する送受信バッファのサイズ(bufferSizeForSockets
)は nn::socket::BUFFER_UNITSIZE_FOR_SOCKETS
( 4096 ) の倍数でなければなりません。
ソケットごとに割り当てる送受信バッファは nn::socket::SetSockOpt()
で指定することができます。デフォルトでは 1 ソケットあたりの送受信バッファに、TCP の場合は 16 KByte(送信 8 KByte、受信 8 KByte)、UDP の場合は 32 KByte が割り当てられます。bufferSizeForSockets
には、最大ソケット数が 1 であっても、最低でも 64 KByte 程度は確保してください。
maxSessions
にはソケットを使用するスレッドの数(最大セッション数)を指定します。処理がブロックされるライブラリ関数の呼び出しを指定された数までのスレッドから受け付けることができます。厳密には、ブロックするライブラリ関数を同時に呼び出さなければ指定数以上のスレッドからライブラリ関数を呼び出すことができますが、そのような運用は推奨しません。ライブラリ関数の呼び出し中に最大セッション数を超えた場合、非同期呼び出し、同期呼び出しに関わらず、セッションが空くまで処理がブロックされます。また、データの着信や送信完了などでブロックが解除される条件を満たしていても、セッションが空くまで処理はブロックされます。非同期処理のはずが、同期処理と同じような挙動になる恐れがありますので注意してください。nn::socket::Poll()
を利用すれば、ソケットの状態を一回の呼び出しで確認することができますので、必要なセッションの数を減らすことができます。
デフォルトで割り当てられる送受信バッファのサイズは、今後変更になる可能性があります。
6.1.2. ソケットの作成
リモートホストもそこに接続するローカル(マシン)も、まずソケットを作成しなければなりません。ソケットの作成は nn::socket::Socket()
の呼び出しで行われます。アプリケーションで同時に使用することのできるソケットの数は 16 に制限されています。
同時使用可能ソケット数は、今後変更になる可能性があります。
s32 nn::socket::Socket(s32 af, s32 type, s32 protocol);
af
に指定することができるのは PF_INET
のみです。
type
には作成するソケットの種類を SOCK_STREAM
(ストリーム)または SOCK_DGRAM
(データグラム)から指定します。ストリームソケットは双方のソケットから接続を確立させる必要がありますが、データグラムソケットは一方的な送信と受信をデータブロック単位で行います。また、前者はデータブロックの到達順が保証されていますが、後者は保証されていない代わりに通信速度が高速になるという利点があります。
protocol
にはソケットに用いるプロトコルを指定しますが、現時点では 0 を指定してください。protocol
が 0 の場合、af
と type
で指定したプロトコルファミリとタイプに対するデフォルトのプロトコルが使われます。デフォルトのプロトコルは、ストリームソケットならば TCP、データグラムソケットならば UDP です。
返り値に 1 以上が返された場合、返り値はソケットを判別するためのソケット記述子です。0 以下が返された場合はエラーです。下表は発生するエラーの一覧です。
返り値 |
エラーの詳細 |
---|---|
|
ライブラリが初期化されていません。 |
|
指定されたプロトコルファミリはサポートしていません。 |
|
指定されたプロトコルはサポートされていません。 |
|
ソケット記述子をこれ以上作成することはできません。 |
|
メモリ不足のため、ワークメモリを確保することができません。 |
|
指定されたソケットの種類はサポートしていません。 |
|
不正な呼び出しです。 |
|
ローカルのネットワークインタフェースがダウンしています。 |
EBUSY
|
内部処理がビジー状態です。Initialize() で指定するセッションが不足している可能性があります。 |
6.1.3. アドレスとポート番号の結び付け
ソケットは、どのアドレスでどのポート番号であるかを示すソケットアドレスが結び付けられて(バインドされて)いなければ通信を行うことができません。作成されただけのソケットには、まだソケットアドレスが結び付けられていません。ソケットアドレスをソケットに結び付けるには nn::socket::Bind()
を呼び出します。
s32 nn::socket::Bind(s32 s, const nn::socket::SockAddrIn* sockAddr);
s
には作成したソケットのソケット記述子を指定します。すでにソケットアドレスが結び付けられているソケットを指定した場合はエラーとなります。
sockAddr
にはソケットアドレス(アドレスファミリ、ポート番号、アドレス)を設定した nn::socket::SockAddrIn
構造体へのポインタを渡します。アドレスの指定は IPv4 のみ対応しています。
処理に成功した場合は返り値に 0 が返されます。0 以外が返された場合はエラーです。下表は発生するエラーの一覧です。
返り値 |
エラーの詳細 |
---|---|
|
ライブラリが初期化されていません。 |
|
指定されたソケット記述子が正しくありません。 |
|
ローカルのネットワークインタフェースがダウンしています。 |
|
無効な処理(ソケットがすでにバインド済みなど)です。 |
|
指定されたアドレスファミリはサポートしていません。 |
|
指定されたソケットアドレスはすでに使用されています。 |
EBUSY
|
内部処理がビジー状態です。Initialize() で指定するセッションが不足している可能性があります。 |
6.1.4. 動作モード
ソケットの動作モードを nn::socket::Fcntl()
の呼び出しで取得・設定することができます。
s32 nn::socket::Fcntl(s32 s, s32 cmd, s32 val);
s
には動作モードの設定・取得を行うソケットのソケット記述子を指定します。
cmd
には動作モードを設定する(F_SETFL
)のか、取得する(F_GETFL
)のかを指定します。
val
には 0 または動作モードに設定するフラグの論理和を指定します。cmd
に F_GETFL
を渡している場合、この引数は無視されます。
設定可能なフラグは O_NONBLOCK
(非封鎖モード)だけです。このフラグが設定されていないソケットの動作モードは封鎖モードとなります。ソケット作成時は封鎖モードに設定されています。
cmd
に F_GETFL
を渡している場合の返り値は、設定されている動作モードを示すフラグの論理和です。cmd
に F_SETFL
を渡している場合、返り値に 0 が返されたときは処理に成功しています。どちらの場合も、負の値が返されたときはエラーです。下表は発生するエラーの一覧です。
返り値 |
エラーの詳細 |
---|---|
|
ライブラリが初期化されていません。 |
|
指定されたソケット記述子が正しくありません。 |
|
ローカルのネットワークインタフェースがダウンしています。 |
|
無効な処理(cmd の指定が不正)です。 |
EBUSY
|
内部処理がビジー状態です。Initialize() で指定するセッションが不足している可能性があります。 |
6.1.5. 接続の待ち受け
データグラムソケットはソケットアドレスのバインドが完了してすぐにデータの送受信を行うことができますが、ストリームソケットはデータの送受信を行う前に接続を確立していなければなりません。
サーバー側となるストリームソケットは、nn::socket::Listen()
でクライアント側となるストリームソケットからの接続要求を待ち受けるキューを作成し、nn::socket::Accept()
で着信(接続要求)を受け付けます。
s32 nn::socket::Listen(s32 s, s32 backlog); s32 nn::socket::Accept(s32 s, nn::socket::SockAddrIn* sockAddr);
どちらの関数でも、s
には待ち受けに使用するソケットを指定します。このソケットはストリームソケットとして作成され、ソケットアドレスがバインドされていなければなりません。
backlog
にはソケットのリッスンバックログとして使用するキューの最大数を指定します。0 または負の値を指定した場合は 1 を指定したものとみなされます。
sockAddr
には受け付けた着信のソケットアドレスを格納する nn::socket::SockAddrIn
構造体へのポインタを指定します。
nn::socket::Listen()
の返り値に 0 が返された場合は処理に成功しています。負の値が返された場合はエラーです。
nn::socket::Accept()
は接続待ちのソケットがキューに存在しない場合、待ち受けに使用しているソケットが非封鎖モードでなければ処理をブロックします。返り値に 1 以上が返された場合、返り値は待ち受けに使用しているソケットと同じアドレスで新たに作成されたソケットのソケット記述子です。0 以下が返された場合はエラーです。
下表は発生するエラーの一覧です。
返り値 |
エラーの詳細 |
---|---|
|
ライブラリが初期化されていません。 |
|
指定されたソケット記述子が正しくありません。 |
|
サポートされていない処理です。 |
|
無効な処理です。 |
|
リソースが不足しています。 |
|
接続待ちのソケットがありません。(非封鎖モード) |
|
接続がキャンセルされました。 |
EMFILE
|
ソケット記述子をこれ以上作成することはできません。 |
|
リッスンバックログ作成のためのメモリが不足しています。 |
|
|
ENETDOWN
|
ローカルのネットワークインタフェースがダウンしています。 |
EBUSY
|
内部処理がビジー状態です。Initialize() で指定するセッションが不足している可能性があります。 |
6.1.6. リモートホストへの接続
クライアント側となるストリームソケットはサーバー側のストリームソケットに nn::socket::Connect()
で接続を試み、接続が確立されるまでデータの送受信を行うことはできません。データグラムソケットが nn::socket::Connect()
を呼び出した場合は、送信先ソケットアドレスの書き換えだけが行われます。
s32 nn::socket::Connect(s32 s, const nn::socket::SockAddrIn* sockAddr);
s
には接続に使用するソケットのソケット記述子を指定します。ソケットにソケットアドレスがまだ結び付けられていない場合は、関数内で未使用のローカルソケットアドレスに結び付けられます。
sockAddr
には接続先のソケットアドレスを設定した nn::socket::SockAddrIn
構造体へのポインタを指定します。
処理に成功した場合は返り値に 0 が返されます。0 以外が返された場合はエラーです。発生するエラーの一覧は以下のようになっています。
返り値 |
エラーの詳細 |
---|---|
|
ライブラリが初期化されていません。 |
EAFNOSUPPORT
|
指定されたプロトコルファミリはサポートしていません。 |
|
指定されたソケット記述子が正しくありません。 |
|
既に非封鎖モードで接続を試みています。 |
|
接続する相手と同時オープンになった後、リセットされました。 |
|
接続がリセットされました。 |
|
指定されたソケットは現在状態を変更しています。 |
|
無効な処理( |
|
すでに使用されているソケットのため、処理に利用できません。 |
|
ローカルのネットワークインタフェースがダウンしています。 |
|
接続先が見つかりません。 |
|
空いているソケットへのソケットアドレスの一時割り当てに失敗しました。 |
|
接続先の応答がタイムアウトしました。 |
EBUSY
|
内部処理がビジー状態です。Initialize() で指定するセッションが不足している可能性があります。 |
s
に指定したソケットがデータグラムソケットの場合、ソケットの送信先ソケットアドレスが sockAddr
に設定されているソケットアドレスに書き換えられるだけですので、動作モードによる処理の違いはありません。
s
に指定したソケットがストリームソケットの場合、動作モードが封鎖モードならば接続が確立するまで処理がブロックされます。非封鎖モードならばすぐに制御が戻され、接続が確立しているかどうかは nn::socket::Poll()
で確認することができます。
struct nn::socket::PollFd { s32 fd; s32 events; s32 revents; }; s32 nn::socket::Poll(nn::socket::PollFd fds[], u32 nfds, s32 timeout);
nn::socket::Poll()
は複数のソケット記述子から、送受信が可能な状態のソケットがあるかどうかを調査します。
fds
には調査対象のソケット記述子と調査条件を設定した nn::socket::PollFd
構造体の配列を指定します。構造体のメンバ変数 fd
には調査対象のソケット記述子を、events
には調査条件を設定します。revents
には調査結果が格納されますので 0 を設定してください。
nn::socket::Connect()
で接続が確立できなかった場合、revents
には POLLRDNORM
と POLLWRNORM
のフラグが立てられ、そのあとのデータの送受信時にエラーが返されます。下表は、events
に設定する調査条件と revents
に格納される調査結果のフラグの一覧です。
フラグ |
説明 |
---|---|
|
受信可能状態を示すフラグです。 |
|
受信可能状態(優先データ)を示すフラグです。 |
|
受信可能状態(最優先データ)を示すフラグです。 |
|
送信可能状態を示すフラグです。 |
|
送信可能状態(優先データ)を示すフラグです。 |
|
エラーが発生した状態を示すフラグです。調査結果でのみ設定されます。 |
|
ソケットが切断された状態を示すフラグです。調査結果でのみ設定されます。 |
|
不正なソケット記述子が指定された状態を示すフラグです。調査結果でのみ設定されます。 |
|
受信可能状態を示すフラグです。 |
|
送信可能状態を示すフラグです。 |
nfds
には fds
で指定した配列の要素数を指定します。
timeout
には条件に一致するソケットが見つからなかったときのタイムアウト時間をミリ秒単位で指定します。0 以上の値または INFTIM
(タイムアウトなし)で指定してください。
nn::socket::Poll()
を呼び出すと、条件に一致するソケットが見つかるまでブロックは解除されません。ただし、ソケットが見つからないまま指定されたタイムアウト時間が経過するか、ソケットが切断されたりソケットに異常が発生したりしたときにはブロックが解除されます。
返り値に 1 以上が返された場合、返された値は条件に一致したソケットの数です。処理がタイムアウトした場合は 0 が返されます。負の値が返された場合はエラーです。下表は発生するエラーの一覧です。
返り値 |
エラーの詳細 |
---|---|
|
ライブラリが初期化されていません。 |
|
ローカルのネットワークインタフェースがダウンしています。 |
|
無効な処理です。 |
EBUSY
|
内部処理がビジー状態です。Initialize() で指定するセッションが不足している可能性があります。 |
6.1.7. データの受信
データの受信は、nn::socket::RecvFrom()
、nn::socket::Recv()
、nn::socket::Read()
のいずれかの関数で行うことができます。ストリームソケットの場合、サーバー側とクライアント側で接続が確立していなければデータの受信を行うことができません。
s32 nn::socket::RecvFrom(s32 s, void* buf, s32 len, s32 flags, nn::socket::SockAddrIn* sockFrom); s32 nn::socket::Recv(s32 s, void* buf, s32 len, s32 flags); s32 nn::socket::Read(s32 s, void* buf, s32 len); s32 nn::socket::SockAtMark(s32 s);
s
にはローカルソケットのソケット記述子を指定します。
buf
には受信データを格納するバッファへのポインタを、len
にはバッファのバイトサイズをそれぞれ指定します。
flags
には受信時に行う特殊な動作を指示するフラグを指定します。MSG_DONTWAIT
を指定した場合、ソケットの動作モードが封鎖モードであってもブロック状態にはなりません。MSG_PEEK
を指定した場合、データの受信は行われますが状態は変化せず、再度同じデータを受信することができます。MSG_OOB
を指定した場合、帯域外のデータを受信することができます。受信可能なデータに帯域外のデータが含まれているかは nn::socket::SockAtMark()
の返り値が 1 であるかどうかで判断することができ、この関数は TCP プロトコルで緊急データの最後の 1 バイトが受信可能データの先頭にあるかどうかの判断にも使用することができます。
sockFrom
に nn::socket::SockAddrIn
構造体へのポインタを指定した場合、データの送信元ソケットアドレスが格納されます。
ストリームソケットで受信している場合、動作モードが封鎖モードならばデータを受信するまで処理がブロックされます。動作モードが非封鎖モードもしくは flags
に MSG_DONTWAIT
を指定しているときは、関数の呼び出し時に受信可能なデータのみをバッファに格納するため、処理がブロックされません。
データグラムソケットで受信している場合、受信データのすべてを 1 回の呼び出しで受信しなければなりません。受信データがバッファ以上のサイズである場合、flags
に MSG_PEEK
が指定されていなければ、バッファを超過したデータが破棄されてしまいます。1 回の呼び出しで受信できるデータの最大サイズは 1500 バイトです。
返り値に 1 以上が返された場合、返された値は受信したデータのバイト数です。ストリームソケットで返り値に 0 が返された場合、リモートホストからのデータ送信が終了したことを示します。データグラムソケットでは 0 が返されることはありません。負の値が返された場合はエラーです。下表は発生するエラーの一覧です。
返り値 |
エラーの詳細 |
---|---|
|
ライブラリが初期化されていません。 |
|
指定されたソケット記述子が正しくありません。 |
|
受信待ちのデータがありません。(非封鎖モードまたは |
|
無効な処理です。 |
|
サポートされていない処理です。 |
|
指定されたソケットはリモートホストに接続されていません。 |
|
接続がリセットされました。 |
|
処理が中止されました。 |
|
処理がタイムアウトしました。 |
|
ローカルのネットワークインタフェースがダウンしています。 |
|
|
EBUSY
|
内部処理がビジー状態です。Initialize() で指定するセッションが不足している可能性があります。 |
6.1.8. データの送信
データの送信は、nn::socket::SendTo()
、nn::socket::Send()
、nn::socket::Write()
のいずれかの関数で行うことができます。ストリームソケットの場合、サーバー側とクライアント側で接続が確立していなければデータの送信を行うことができません。
s32 nn::socket::SendTo(s32 s, const void* buf, s32 len, s32 flags, const nn::socket::SockAddrIn* sockTo); s32 nn::socket::Send(s32 s, const void* buf, s32 len, s32 flags); s32 nn::socket::Write(s32 s, const void* buf, s32 len);
s
にはローカルソケットのソケット記述子を指定します。
buf
には送信データが格納されているバッファへのポインタを、len
にはバッファのバイトサイズをそれぞれ指定します。
flags
には送信時に行う特殊な動作を指示するフラグを指定します。
sockTo
に nn::socket::SockAddrIn
構造体へのポインタを指定した場合、構造体に設定されているソケットアドレスにデータを送信します。
データの送信が完了するまで処理がブロックされます。
データグラムソケットで送信している場合、1 回の呼び出しで送信できるデータの最大サイズは 1500 バイトです。
処理に成功した場合は返り値に 0 が返されます。負の値が返された場合はエラーです。下表は発生するエラーの一覧です。
返り値 |
エラーの詳細 |
---|---|
|
ライブラリが初期化されていません。 |
EAFNOSUPPORT
|
指定されたプロトコルファミリはサポートしていません。 |
|
指定されたソケット記述子が正しくありません。 |
|
封鎖モードの場合、すでに送信を試みましたがブロックされています。 非封鎖モードのストリームソケットの場合、帯域外に送信しようとするデータを内部送信バッファに送信予約できません。 |
|
接続がリセットされました。 |
|
処理が中止されました。 |
|
無効な処理です。 |
|
サポートされていない処理です。 |
|
ストリームソケットの場合、ソケットは接続要求を受け付けるために使用されています。 データグラムソケットの場合、データを送信しようとする通信先のソケットアドレスが決まっていません。 |
|
データが内部送信バッファのサイズを超えています。(データグラムソケットのみ) |
|
ローカルのネットワークインタフェースがダウンしています。 |
|
接続先が見つかりません。 |
|
空いているソケットへのソケットアドレスの一時割り当てに失敗しました。または、一時送信バッファの確保に失敗しました。 |
|
指定されたソケットはリモートホストに接続されていません。 |
|
処理がタイムアウトしました。 |
|
|
EBUSY
|
内部処理がビジー状態です。Initialize() で指定するセッションが不足している可能性があります。 |
6.1.9. オプション設定
nn::socket::SetSockOpt()
と nn::socket::GetSockOpt()
の呼び出しで、ソケットの内部設定値や内部状態情報など、オプション設定の変更と取得を行うことができます。
s32 nn::socket::SetSockOpt(s32 s, s32 level, s32 optname, const void* optval, s32 optlen); s32 nn::socket::GetSockOpt(s32 s, s32 level, int optname, void* optval, int* optlen)
引数に指定可能な値についてはヘッダファイル(nn/socket/socket_User.autogen.h)を参照してください。
処理に成功した場合は返り値に 0 が返されます。負の値が返された場合はエラーです。下表は発生するエラーの一覧です。
返り値 |
エラーの詳細 |
---|---|
|
ライブラリが初期化されていません。 |
|
指定されたソケット記述子が正しくありません。 |
|
無効な処理です。 |
|
ローカルのネットワークインタフェースがダウンしています。 |
|
メモリ不足のため、ワークメモリを確保することができません。 |
|
サポートされていないオプションです。 |
EBUSY
|
内部処理がビジー状態です。Initialize() で指定するセッションが不足している可能性があります。 |
6.1.10. ソケットの切断
nn::socket::Shutdown()
の呼び出しで、ソケット通信を遮断してソケットを切断することができます。
s32 nn::socket::Shutdown(s32 s, s32 how);
s
にはソケット通信を遮断するソケットのソケット記述子を指定します。
how
には遮断方法を指定します。以降のデータの受信を遮断する場合は SHUT_RD
を、送信を遮断する場合は SHUT_WR
を、送受信ともに遮断する場合は SHUT_RDWR
を指定してください。
処理に成功した場合は返り値に 0 が返されます。負の値が返された場合はエラーです。下表は発生するエラーの一覧です。
返り値 |
エラーの詳細 |
---|---|
|
ライブラリが初期化されていません。 |
|
指定されたソケット記述子が正しくありません。 |
|
指定されたソケットはリモートホストに接続されていません。 |
|
無効な処理です。 |
EBUSY
|
内部処理がビジー状態です。Initialize() で指定するセッションが不足している可能性があります。 |
6.1.11. ソケットの破棄
同時に使用することのできるソケットの数は制限されています。不要になったソケットは nn::socket::Close()
を呼び出して破棄してください。
s32 nn::socket::Close(s32 s);
s
には破棄する(閉じる)ソケットのソケット記述子を指定します。
ソケットが閉じられると、そのソケットは以後使用できなくなります。閉じられるソケットを使用して呼び出された関数の処理がブロックされている場合、それぞれの関数のブロックが解除されてエラーが返されます。非封鎖モードに設定されていないストリームソケットが閉じられる場合、Linger オプションの設定に従って接続が閉じられます。
デフォルトでは、この関数はブロックせずに処理をすぐに返します。そして、バックグランドで残りの送信データを自動的に転送し、そのあとでソケットが使用していたリソースを解放します。
処理に成功した場合は返り値に 0 が返されます。負の値が返された場合はエラーです。下表は発生するエラーの一覧です。
返り値 |
エラーの詳細 |
---|---|
|
ライブラリが初期化されていません。 |
|
指定されたソケット記述子が正しくありません。 |
|
指定されたソケットはリモートホストに接続されていません。 |
|
無効な処理です。 |
EBUSY
|
内部処理がビジー状態です。Initialize() で指定するセッションが不足している可能性があります。 |
6.1.12. 終了
SOCKET ライブラリの使用を終了するときは nn::socket::Finalize()
を呼び出して終了処理を行ってください。
nn::Result nn::socket::Finalize(void);
ライブラリが使用していたリソースはすべて解放され、使用中のソケット記述子もすべて破棄されます。
6.1.13. ユーティリティ関数
SOCKET ライブラリには、ソケットアドレスの取得や、ネットワークアダプタ情報の取得、DNS を介したリモートホスト情報の取得、数値と文字列間でのアドレスの相互変換、数値のホストバイトオーダー変換とネットワークバイトオーダー変換などのユーティリティ関数が用意されています。
s32 nn::socket::GetSockName(s32 s, nn::socket::SockAddrIn* sockAddr); s32 nn::socket::GetPeerName(s32 s, nn::socket::SockAddrIn* sockAddr);
nn::socket::GetSockName()
は s
に指定されたソケット記述子で示されるソケットのローカルソケットアドレスを sockAddr
に取得します。ローカルソケットアドレスは通信元のソケットアドレスです。nn::socket::Bind()
や nn::socket::Connect()
でローカルソケットアドレスを確定していない状態で、UDP プロトコルのソケット(データグラムソケット)に対してこの関数を呼び出した場合は 0.0.0.0 のアドレスが返され、TCP プロトコルのソケット(ストリームソケット)に対してこの関数を呼び出すとエラーが返されます。
nn::socket::GetPeerName()
は s
に指定されたソケット記述子で示されるソケットのリモートソケットアドレスを sockAddr
に取得します。リモートソケットアドレスは通信先のソケットアドレスです。
どちらの関数も処理に成功した場合は返り値に 0 が返されます。負の値が返された場合はエラーです。下表は発生するエラーの一覧です。
返り値 |
エラーの詳細 |
---|---|
|
ライブラリが初期化されていません。 |
|
指定されたソケット記述子が正しくありません。 |
|
リモートホストに接続されていないか通信先がいません。( |
|
無効な処理です。 |
|
ローカルのネットワークインタフェースがダウンしています。 |
EBUSY
|
内部処理がビジー状態です。Initialize() で指定するセッションが不足している可能性があります。 |
u32 nn::socket::GetHostId(void);
nn::socket::GetHostId()
はローカルホストの IP アドレス(IPv4)を返します。0 が返されたときはネットワークを使用することができない状態です。返り値は IP アドレスを 32 ビット数値(ネットワークバイトオーダー)にしたものです。
nn::socket::HostEnt* nn::socket::GetHostByName(const char8* name); nn::socket::HostEnt* nn::socket::GetHostByAddr(const void* addr, s32 len, s32 type); s32 nn::socket::GetAddrInfo(const char8* nodeName, const char8* servName, const nn::socket::AddrInfo* hints, nn::socket::AddrInfo** res); void nn::socket::FreeAddrInfo(nn::socket::AddrInfo* head); s32 nn::socket::GetNameInfo(const void* sa, char8* node, s32 nodeLen, char8* service, s32 serviceLen, s32 flags);
nn::socket::GetHostByName()
と nn::socket::GetHostByAddr()
はどちらも指定されたホストの情報を取得します。前者はホスト名またはドット十進記法のアドレスの文字列から、後者はアドレスからホストを検索します。検索中は処理がブロックされ、DNS サーバーへの問い合わせを行う場合があります。返り値が示す構造体の実体はライブラリ内部のバッファですので、これらの関数はスレッドセーフではありません。
nn::socket::GetAddrInfo()
はホスト名とサービス名で検索したホストの情報を取得します。検索動作の設定は hints
に指定された nn::socket::AddrInfo
構造体のメンバ変数 flags
で行います。flags
には nn::socket::AddrInfoFlag
列挙子に定義されているフラグの論理和を設定します。
フラグ |
説明 |
---|---|
|
|
|
|
|
|
|
|
検索中は処理がブロックされ、DNS サーバーへの問い合わせを行う場合があります。res
に返される検索結果の構造体は nn::socket::Initialize()
で指定したアロケータからライブラリが確保したメモリに格納されます。検索結果が不要になったときは nn::socket::FreeAddrInfo()
でライブラリが確保したメモリを解放してください。
nn::socket::GetAddrInfo()
は処理に成功した場合、返り値に 0 を返します。負の値を返した場合はエラーです。下表は発生するエラーの一覧です。
返り値 |
エラーの詳細 |
---|---|
EAI_BADFLAGS
|
hints
に AI_CANONNAME が指定されているにも関わらず nodeName が NULL または空文字列です。 |
|
修復不可能なエラーが発生しました。 |
EAI_FAMILY
|
hints
に指定したアドレスファミリがサポートされていません。 |
|
メモリの確保に失敗しました。 |
|
検索対象のホストが見つかりません。 |
EAI_SOCKTYPE
|
|
EAI_SYSTEM
|
システムエラーが発生しました。Initialize を呼び出さずに本関数を呼び出した場合などに発生します。 |
nn::socket::GetNameInfo()
はアドレスからホスト名とサービス名を検索します。検索動作の設定は flags
に nn::socket::NameInfoFlag
列挙子に定義されているフラグの論理和を指定することで行います。
フラグ |
説明 |
---|---|
|
完全修飾ドメイン名(FQDN)のうちノード名の部分だけをホスト名として取得します。 |
|
|
|
検索対象のホストが見つからない場合に、数値形式のホストアドレスを文字列に変換することで代替せずにエラー( |
|
|
検索中は処理がブロックされ、DNS サーバーへの問い合わせを行う場合があります。
処理に成功した場合は返り値に 0 が返されます。負の値が返された場合はエラーです。下表は発生するエラーの一覧です。
返り値 |
エラーの詳細 |
---|---|
|
|
|
または、 |
EAI_SYSTEM
|
システムエラーが発生しました。Initialize を呼び出さずに本関数を呼び出した場合などに発生します。 |
s32 nn::socket::InetAtoN(const char* cp, nn::socket::InAddr* inp); char* nn::socket::InetNtoA(nn::socket::InAddr in); s32 nn::socket::InetPtoN(int af, const char* src, void* dst); const char* nn::socket::InetNtoP(int af, const void* src, char* dst, unsigned len);
nn::socket::InetAtoN()
と nn::socket::InetNtoA()
を呼び出すことで、アドレスを十進記法の文字列と nn::socket::InAddr
構造体の数値形式間で相互変換することができます。変換することのできるアドレスは IPv4 のホストアドレスで、本来ならば nn::socket::InetPtoN()
と nn::socket::InetNtoP()
はアドレスファミリを指定することができますが、CTR-SDK では AF_INET
のみが指定可能です。
これらの関数は nn::socket::Initialize()
を呼び出していなくても使用することができます。
bit32 nn::socket::HtoNl(bit32 v); bit32 nn::socket::NtoHl(bit32 v); bit16 nn::socket::HtoNs(bit16 v); bit16 nn::socket::NtoHs(bit16 v);
数値を、ホストバイトオーダーからネットワークバイトオーダーへ(HtoN)またはネットワークバイトオーダーからホストバイトオーダーへ(NtoH)変換します。関数名の末尾が "l
" ならば 32 ビット数値、"s
" ならば 16 ビット数値のバイトオーダー変換を行うことができます。
6.2. SSL 通信
SSL(SSL 通信)ライブラリは、ソケット通信をラッピングして通信の秘匿化を補助します。
6.2.1. 初期化
SSL ライブラリの初期化は nn::ssl::Initialize()
の呼び出しで行われます。
nn::Result nn::ssl::Initialize(void);
6.2.2. 接続クラスの生成
SSL 通信は接続クラス(nn::ssl::Connection
)にラッピングされたソケットを介して行われます。
class nn::ssl::Connection { explicit Connection(s32 socket); explicit Connection(); bool AssignSocket(s32 socket); }
コンストラクタにはソケット記述子を引数に持つものと、引数なしのものがあります。引数なしで生成された接続クラスは、メンバ関数の AssignSocket()
でソケットを結び付ける必要があります。
6.2.3. 通信先の設定
メンバ関数の Initialize()
で、通信先のサーバーを接続クラスに設定します。
class nn::ssl::Connection { nn::Result Initialize(const char* pServerName, u32 verifyOpt = VERIFY_NONE); }
pServerName
には通信先サーバーのホスト名を指定します。SSL 通信時には、このホスト名とサーバー証明書の CommonName もしくは subjectAltName 拡張領域の dnsName/ipAddress を比較し、一致していなかった場合は接続エラーを返します。ホスト名として指定できる文字列の長さは、終端文字を含めて nn::socket::MAXDNAME
バイトまでです。
verifyOpt
には SSL 通信のサーバー検証に関するオプションを指定します。デフォルトのサーバー検証を用いる場合はこの引数を省略することができます。デフォルトでは実施されないサーバー検証のオプションを実施するときは、実施する検証オプションを表す nn::ssl::VerifyOption
列挙子を verifyOpt
に指定します。複数の検証オプションを同時に設定したい場合は、その論理和を指定します。引数には、以下の値を設定することができます。
値 |
説明 |
---|---|
|
証明書の期限切れ検証を実施します。 |
|
resumption を利用し、同じホストに連続で接続する際にセッションの再利用を試みます。 |
|
EV 証明書検証を実施します。サーバー証明書が EV 証明書に紐づいたものでない限り、検証は失敗します。 信頼する EV 証明書は |
|
サーバー証明書検証を行いますが、検証結果は無視して接続します。検証結果は、 |
|
|
nn::ssl::VerifyOption
に定義されている上記以外のオプションはデフォルトで実施されます。
証明書チェーン内の全証明書データを保存する場合、データは "[証明書データ長(4 Byte)]+[証明書データ]" が並ぶ形で保存されます。データの並び順は、チェーン先頭の証明書(=サーバー証明書)から、チェーン末尾(CA 証明書)の順です。ただし CA 検証が NG の場合、CA 証明書が特定できなため、CA 証明書データは含まれません。
6.2.4. 証明書と CRL の設定
サーバーとのハンドシェイクに使用する、証明書と CRL の 2 つのストア、クライアント証明書を接続クラスに設定します。
class nn::ssl::Connection { nn::Result SetServerCertStore(nn::ssl::CertStore& certStore); nn::Result SetClientCert(nn::ssl::ClientCert& clientCert); nn::Result SetCRLStore(nn::ssl::CrlStore& crlStore); }
証明書ストアの登録は SetServerCertStore()
で、 CRL ストアの登録は SetCRLStore() で、クライアント証明書の登録は SetClientCert() で行います。
6.2.4.1. 証明書ストアのクラス
証明書ストアのクラスは nn::ssl::CertStore
で定義されています。
class nn::ssl::CertStore { explicit CertStore(); virtual ~CertStore(void); nn::Result Initialize(void); nn::Result Finalize(void); nn::Result RegisterCert(const u8* pCertData, size_t certDataSize, nn::ssl::CertId* pCertIdCourier=NULL); nn::Result RegisterCert(nn::ssl::InternalCaCert inCaCertName, nn::ssl::CertId* pCertIdCourier=NULL); nn::Result UnRegisterCert(nn::ssl::CertId certId); }
コンストラクタに引数はありません。インスタンスを用意し、Initialize()
で初期化を行ってください。
メンバ関数の RegisterCert()
で証明書を証明書ストアに登録します。引数 pCertData
と certDataSize
には、証明書データとそのバイトサイズを指定してください。機器に内蔵された証明書を証明書ストアに登録するためには、代わりに nn::ssl::InternalCaCert を引数に指定します。個別に証明書の登録を解除する必要がなければ、引数 pCertIdCourier
を指定しなくてもかまいません。登録を解除していなかった証明書は、Finalize()
を呼び出したときに登録が解除されます。証明書ストアに複数の証明書を登録する場合は、続けて RegisterCert()
メンバ関数を呼び出してください。
メンバ関数の UnRegisterCert()
で証明書ストアから個別に証明書の登録を解除することができます。RegisterCert()
で証明書を登録したときに pCertIdCourier
で受け取った証明書 ID を certId
に指定してください。
証明書ストアが不要になったときには、必ず Finalize()
を呼び出してください。
6.2.4.2. CRL ストアのクラス
CRL ストアのクラスは nn::ssl::CrlStore
で定義されています。
class nn::ssl::CrlStore { explicit CrlStore(); virtual ~CrlStore(void); nn::Result Initialize(void); nn::Result Finalize(void); nn::Result RegisterCrl(const u8* pCrlData, size_t crlDatasize, nn::ssl::CrlId* pCrlIdCourier=NULL); nn::Result RegisterCrl(nn::ssl::InternalCrl inCrlName, nn::ssl::CrlId* pCrlIdCourier=NULL); nn::Result UnRegisterCrl(nn::ssl::CrlId crlId); }
コンストラクタに引数はありません。インスタンスを用意し、Initialize()
で初期化を行ってください。
メンバ関数の RegisterCrl()
で CRL を CRL ストアに登録します。引数 pCrlData
と crlDatasize
には、CRL データとそのバイトサイズを指定してください。機器に内蔵された CRL を CRL ストアに登録するためには、代わりに nn::ssl::InternalCrl を引数に指定します。個別に CRL の登録を解除する必要がなければ、引数 pCrlIdCourier
を指定しなくてもかまいません。登録を解除していなかった CRL は、Finalize()
を呼び出したときに登録が解除されます。CRL ストアに複数の CRL を登録する場合は、続けて RegisterCrl()
メンバ関数を呼び出してください。
メンバ関数の UnRegisterCrl()
で CRL ストアから個別に CRL の登録を解除することができます。RegisterCrl()
で CRL を登録したときに pCrlIdCourier
で受け取った CRL の ID を crlId
に指定してください。
CRL ストアが不要になったときには、必ず Finalize()
を呼び出してください。
6.2.4.3. クライアント証明書のクラス
クライアント証明書のクラスは nn::ssl::ClientCert
で定義されています。
class nn::ssl::ClientCert { explicit ClientCert(); virtual ~ClientCert(void); nn::Result Initialize(const u8* pCertData, size_t certDataSize, const u8* pPrivateKeyData, size_t privateKeyDataSize); nn::Result Initialize(nn::ssl::InternalClientCert inClientCertName); nn::Result Finalize(void); }
コンストラクタに引数はありません。インスタンスを用意し、Initialize()
で初期化を行います。
引数 pCertData
と certDataSize
には、クライアント証明書の証明書データとそのバイトサイズを指定してください。引数 pPrivateKeyData
と privateKeyDataSize
には、秘密鍵のデータとそのバイトサイズを指定してください。内蔵のクライアント証明書を使用する場合には、代わりに nn::ssl::InternalClientCert を指定します。
クライアント証明書が不要になったときには、必ず Finalize()
を呼び出してください。
6.2.5. ハンドシェイク
メンバ関数の DoHandshake()
で、接続クラスに設定された証明書ストア、CRL ストア、クライアント証明書を使って、接続先のサーバーとのハンドシェイクを行います。
class nn::ssl::Connection { nn::Result SetServerCertBuffer(uptr bufferAddress, size_t bufferSize); nn::Result DoHandshake(void); nn::Result DoHandshake(size_t* pServerCertSize, u32* pServerCertNum = NULL); }
サーバーから通知されたサーバー証明書についての情報が必要なときは、引数ありの DoHandshake()
を呼び出してください。サーバー証明書のバイトサイズは pServerCertSize
に指定された変数のポインタに格納されます。
サーバー証明書を格納するバッファは SetServerCertBuffer()
で指定します。指定するバッファはデバイスメモリ以外から確保しなければなりません。また、指定するバッファの先頭アドレスは nn::ssl::Connection::BUFFER_ALIGNMENT
( 4096 Byte ) のアライメント、サイズは nn::ssl::Connection::BUFFER_UNITSIZE
( 4096 ) の倍数でなければなりません。SetServerCertBuffer()
でバッファを指定せずに引数ありの DoHandshake()
を呼び出した場合は、引数なしの DoHandshake()
を呼び出したときと同じ動作になります。
6.2.6. データの送受信
ハンドシェイクに成功したことを確認できたら、SSL 接続経由でのデータの送受信を開始することができます。
class nn::ssl::Connection { nn::Result Read(u8* pDataBuf, size_t dataBufSize, size_t* pReadSizeCourier = NULL); nn::Result Peek(u8* pDataBuf, size_t dataBufSize, size_t* pReadSizeCourier = NULL); nn::Result Write(const u8* pDataBuf, size_t dataBufSize, size_t* pWrittenDataSizeCourier = NULL); }
Read()
と Peek()
はともにデータの受信を行うメンバ関数ですが、Peek()
で受信した場合は状態を変化させずに受信済みのデータを受け取ることができます。引数 pDataBuf
と dataBufSize
には、受信データを受け取るバッファとそのバイトサイズを指定してください。引数 pReadSizeCourier
には、受け取ったデータのサイズが必要な場合にサイズを受け取る変数のポインタを指定してください。
Write()
はデータの送信を行うメンバ関数です。引数 pDataBuf
と dataBufSize
には、送信するデータが格納されているバッファとそのバイトサイズを指定してください。引数 pWrittenDataSizeCourier
には、送信されたデータのサイズが必要な場合にサイズを受け取る変数のポインタを指定してください。
6.2.7. 接続の切断
同時に使用することのできる SSL 接続の数は制限されています。そのため、不要になった接続クラスに対してメンバ関数 Shutdown()
を呼び出し、SSL 接続の切断と終了処理を行ってください。
class nn::ssl::Connection { nn::Result Shutdown(void); }
6.2.8. 終了
6.3. HTTP 通信
HTTP(HTTP 通信)ライブラリは、指定された URL へ接続して HTTP プロトコルでのネットワーク通信を行うライブラリです。HTTPS 通信にも対応しています。
6.3.1. 初期化
HTTP ライブラリの初期化は nn::http::Initialize()
の呼び出しで行われます。
nn::Result nn::http::Initialize(uptr bufferAddress = 0, size_t bufferSize = 0);
HTTP ライブラリを利用するときは、事前にこの関数を呼び出しておかなければなりません。すでに初期化が行われている場合は、返り値に nn::http::ResultAlreadyInitializedErr
が返されます。
bufferAddress
と bufferSize
を指定します。通信用バッファとして渡すバッファは デバイスメモリ以外から確保 しなければなりません。また、バッファの先頭アドレスのアライメントは nn::http::BUFFER_ALIGNMENT
( 4096 Byte )、バッファのサイズは nn::http::BUFFER_UNITSIZE
( 4096 ) の倍数でなければなりません。
6.3.2. 接続クラスの生成
HTTP 接続には nn::http::Connection
クラスを使用します。このクラスのインスタンスは、1 URL への接続と通信を単位に生成しなければなりません。システム全体およびアプリケーションで同時に使用することのできる通信リソース(接続数)には制限がありますので、接続数の管理には注意してください。
コンストラクタには、引数ありとなしの 2 種類が用意されています。引数なしのコンストラクタでインスタンスを生成した場合は、メンバ関数の Initialize()
を呼び出して、接続先の URL とメソッド、デフォルトプロキシの使用についての設定を行う必要があります。
class nn::http::Connection { explicit Connection(void); explicit Connection(const char* pUrl, RequestMethod method = REQUEST_METHOD_GET, bool isUseDefaultProxy = true); nn::Result Initialize(const char* pUrl, RequestMethod method = REQUEST_METHOD_GET, bool isUseDefaultProxy = true); }
pUrl
には接続先の URL を指定します。
method
には HTTP リクエストのメソッドを指定します。メソッドは以下の 3 種類から選択します。
定義 |
メソッドの種類 |
---|---|
|
GET メソッド。送信するデータは接続先の URL に埋め込みます。 |
|
POST メソッド。送信するデータは POST データとして追加します。 |
|
HEAD メソッド。接続先の URL からメッセージヘッダだけを受信します。 |
isUseDefaultProxy
に true
を指定した場合は、接続時にデフォルトのプロキシ設定を利用します。デフォルト以外のプロキシ設定を利用する場合はこの引数に false
を指定し、別途プロキシの設定を行ってください。
Initialize()
で返される nn::Result
クラスがエラーのときは、Description でエラーの原因を判断することができます。
Description の値 |
エラーの原因 |
---|---|
|
システム全体の通信リソースに空きがありません。 |
|
指定された URL が不正です。 |
|
すでに接続先の URL が指定されています。 |
|
アプリケーションに割り当てられている通信リソースに空きがありません。 |
6.3.3. 通信設定
プロキシ設定やベーシック認証の設定、通信時に使用するソケットの受信バッファサイズの設定など、通信に関する設定を行います。これらの設定は接続を開始する前に行わなければなりません。
class nn::http::Connection { nn::Result SetProxy(const char* pProxyName, u16 port, const char* pUserName, const char* pPassword); nn::Result SetBasicAuthorization(const char* pUserName, const char* pPassword); }
デフォルトのプロキシ設定を利用しない場合は、SetProxy()
でプロキシ設定を行います。pProxyName
と port
にはプロキシの URL とポート番号を、pUserName
と pPassword
には認証に使用するユーザーとパスワードを指定します。
接続時にベーシック認証が必要な場合は、SetBasicAuthorization()
でベーシック認証の設定を行います。pUserName
と pPassword
には認証に使用するユーザーとパスワードを指定します。
6.3.3.1. HTTPS 通信を行う場合の設定
HTTPS 通信を行う場合は、CA 証明書や CRL 、クライアント証明書など、SSL 通信に必要な設定を行わなければなりません。
class nn::http::Connection { nn::Result SetRootCa(const u8* pCertData, size_t certDataSize); nn::Result SetRootCa(nn::http::InternalCaCertId inCaCertName); nn::Result SetRootCaStore(nn::http::CertStore& certStore); nn::Result SetCrl(const u8* pCrlData, size_t crlDataSize); nn::Result SetCrl(nn::http::InternalCrlId inCrlName); nn::Result SetCrlStore(CrlStore& crlStore); nn::Result SetClientCert(const u8* pCertData, size_t certDataSize, const u8* pPrivateKeyData, size_t privateKeyDataSize); nn::Result SetClientCert(nn::http::InternalClientCertId inClientCertName); nn::Result SetClientCert(nn::http::ClientCert& clientCert); nn::Result GetSslError(s32* pResultCodeBuf) const; nn::Result SetVerifyOption(u32 verifyOption); nn::Result DisableVerifyOptionForDebug(u32 excludeVerifyOptions); }
CA 証明書の登録は SetRootCa()
で行います。証明書は証明書データを直接登録することも、機器に内蔵された CA 証明書を nn::http::InternalCaCertId
で指定して登録することもできます。
複数の CA 証明書を設定する必要がある場合は、SetRootCa()
を複数回呼び出して設定する以外にも、nn::http::CertStore
クラスのインスタンスを引数に SetRootCaStore()
を呼び出して設定することもできます。この場合、複数の接続で同じ CA 証明書セットを利用することができます。
CA 証明書セットを利用して通信しているときは、nn::http::CertStore
クラスのインスタンスを破棄しないでください。
class nn::http::CertStore { explicit CertStore(); virtual ~CertStore (void); nn::Result Initialize(void); nn::Result Finalize(void); nn::Result RegisterCert(const u8* pCertData, size_t certDataSize, nn::http::CertId* pCertIdCourier=NULL); nn::Result RegisterCert(nn::http::InternalCaCertId inCaCertName, nn::http::CertId* pCertIdCourier=NULL); nn::Result UnRegisterCert(nn::http::CertId certId); }
nn::http::CertStore
クラスを利用するときは、必ず Initialize()
で初期化を行ってください。CA 証明書の登録は RegisterCert()
で行います。複数回呼び出すことで、複数の CA 証明書が登録された CA 証明書セットになります。
個別に CA 証明書の登録を解除する場合は、登録時に pCertIdCourier
に返される値を引数に UnRegisterCert()
を呼び出してください。インスタンスそのものが不要になったときは、必ず Finalize()
で終了処理を行ってから破棄してください。
CRL の登録は SetCrl() で行います。 CRL データを直接登録することも、機器に内蔵された CA 証明書を nn::http::InternalCrlId で指定して登録することもできます。ただし、現時点では内蔵 CRL は存在しません。
CA 証明書の登録と同じように、複数の CRL を設定する必要がある場合は、 SetCrl() を複数回呼び出して設定する以外にも、 nn::http::CrlStore クラスのインスタンスを引数に SetCrlStore() を呼び出して設定することができます。 nn::http::CrlStore クラスの使い方は nn::http::CertStore クラスと同様です。
class nn::http::CrlStore { explicit CrlStore(); virtual ~CrlStore (void); nn::Result Initialize(void); nn::Result Finalize(void); nn::Result RegisterCrl(const u8* pCrlData, size_t crlDataSize, nn::http::CrlId* pCrlIdCourier=NULL); nn::Result RegisterCrl(nn::http::InternalCrlId inCrlName, nn::http::CrlId* pCrlIdCourier=NULL); nn::Result UnRegisterCrl(nn::http::CrlId crlId); }
クライアント証明書の設定は SetClientCert()
で行います。設定の方法には、証明書と秘密鍵を指定する方法と機器に内蔵されているクライアント証明書を指定する方法、nn::http::ClientCert
クラスのインスタンスを利用して複数の接続で同じクライアント証明書を利用する方法があります。
nn::http::ClientCert
クラスを複数の接続で利用する場合は、通信中にインスタンスを破棄しないでください。
class nn::http::ClientCert { explicit ClientCert(); virtual ~ClientCert (void); nn::Result Initialize(const u8* pCertData, size_t certDataSize, const u8* pPrivateKeyData, size_t privateKeyDataSize); nn::Result Initialize(nn::http::InternalClientCertId inClientCertName); nn::Result Finalize(void); }
nn::http:ClientCert
クラスの初期化関数 Initialize()
には、証明書と秘密鍵を指定するものと、機器に内蔵されているクライアント証明書を指定するものがあります。インスタンスが不要になったときは、必ず Finalize()
で終了処理を行ってから破棄してください。
デフォルトでは有効となっていないサーバーの検証オプションを SetVerifyOption()
で有効にすることができます。デフォルトでは、VERIFY_COMMON_NAME
(CommonName 検証)、VERIFY_ROOT_CA
(RootCA 検証)、VERIFY_SUBJECT_ALT_NAME
(SubjectAlternativeName 検証)が有効となっています。
現在、追加で有効にすることができる検証オプションは、VERIFY_DATE
(証明書の期限切れ検証)、USE_SESSION_CACHE
(resumption の利用)、VERIFY_EV
(EV 証明書検証)の 3 つです。
DisableVerifyOptionForDebug()
で検証オプションを無効にすることができますが、デバッグ目的以外での使用はなるべく控えてください。
HTTPS 通信中に発生したエラーは GetSslError()
の引数 pResultCodeBuf
に格納される値で判断することができます。格納されるエラーコードは nn::ssl::ResultCode
で定義されている値です。
6.3.4. 送信データの設定
接続を開始してデータを送信する前に、メッセージフィールドのヘッダの追加や、POST データの追加を行います。後述する POST データ遅延設定モードを利用すると、接続を開始したあとに POST データを追加することができます。
class nn::http::Connection { nn::Result AddHeaderField(const char* pLabel, const char* pValue); nn::Result SetPostDataEncoding(nn::http::EncodingType type); nn::Result AddPostDataAscii(const char* pLabel, const char* pValue); nn::Result AddPostDataBinary(const char* pLabel, const void* pValue, size_t valueSize); nn::Result AddPostDataRaw(const void* pValue, size_t valueSize); }
メッセージフィールドにヘッダを追加するには AddHeaderField()
を呼び出してください。たとえば、pLabel
と pValue
に "Connection"
と "keep-alive"
を指定すると、Connection ラベルに "keep-alive" を指定したヘッダが追加されます。
POST データを追加するには、最初に SetPostDataEncoding()
でエンコードの方法を指定し、AddPostDataAscii()
などで POST データを追加します。
type
に渡すエンコードの方法は、nn::http::EncodingType
列挙子に定義された値から選択します。
定義 |
説明 |
---|---|
|
すべて |
|
データを URL エンコードして送信します。POST データを追加するときは、 |
|
データをエンコードせずに送信します。 |
AddPostDataAscii()
で追加された POST データ(ASCII 文字列)は、URL エンコードされて送信される場合にはラベル、データともにエンコードされます。POST データにバイナリが含まれる場合や、エンコード方法にマルチパートを指定した場合はラベルもデータもエンコードされません。
AddPostDataBinary()
で追加された POST データ(バイナリデータ)は、エンコードされずにそのまま送信されます。
AddPostDataRaw()
は上記 2 つの関数とは異なり、複数の POST データを一括して追加する場合に呼び出します。POST データにはバイナリ形式のみ指定可能です。この関数のあとに AddPostDataAscii()
や AddPostDataBinary()
を呼び出した場合は Description に ER_POST_ADDED_ANOTHER
が設定されたエラーが返されます。また、再度 AddPostDataRaw()
を呼び出した場合は前に追加したデータが破棄され、新たに追加したデータが有効になります。
6.3.4.1. POST データ遅延設定モード
POST データ遅延設定モードを利用すると、接続を開始したあとに POST データを送信することができます。このモードで POST データを送信する場合は、SendPostData*()
が同期処理のため、送信が完了するまで処理がブロックされることに注意してください。ただし、引数 timeout
を持つオーバーロードは指定された時間で処理をタイムアウトさせることができます。タイムアウトした場合、内部で Cancel()
が呼び出され、接続はキャンセル状態になります。
class nn::http::Connection { nn::Result SetLazyPostDataSetting(nn::http::PostDataType dataType); nn::Result NotifyFinishSendPostData(void); nn::Result SendPostDataAscii(const char* pLabel, const char* pValue); nn::Result SendPostDataAscii(const char* pLabel, const char* pValue, const nn::fnd::TimeSpan& timeout); nn::Result SendPostDataBinary( const char* pLabel, const void* pValue, size_t valueSize); nn::Result SendPostDataBinary( const char* pLabel, const void* pValue, size_t valueSize, const nn::fnd::TimeSpan& timeout); nn::Result SendPostDataRaw(const void* pValue, size_t valueSize); nn::Result SendPostDataRaw(const void* pValue, size_t valueSize, const nn::fnd::TimeSpan& timeout); }
POST データ遅延設定モードは SetLazyPostDataSetting()
の呼び出しで行います。引数 dataType
で指定する送信データのタイプによって、POST データ送信のために呼び出すことのできる関数とデータの送信方法が異なります。送信データのタイプは nn::http::PostDataType
列挙子に定義された値から選択します。
定義 |
説明 |
---|---|
|
URL エンコード形式で送信します。 |
|
マルチパート形式で送信します。 |
|
RAW 形式で送信します。 |
URL エンコード形式で送信する場合、送信のために呼び出すことのできる関数は SendPostDataAscii()
と SendPostDataBinary()
です。SendPostDataAscii()
を呼び出した場合は URL エンコードされた「(ラベル名)=(データ内容)」という内容のデータが送信され、SendPostDataBinary()
を呼び出した場合はエンコードされていない同じ内容のデータが送信されます。
マルチパート形式で送信する場合、送信のために呼び出すことのできる関数は SendPostDataAscii()
と SendPostDataBinary()
です。1 回の呼び出しで送信されるデータは、boundary データとヘッダフィールドを先頭に付与した Chunked データとしてまとめて送信されます。ラベル名が "Content-Disposition: form-data; name=(ラベル名)" というヘッダフィールドとして boundary データのあとに付与されるのはどちらの関数でも同じですが、SendPostDataBinary()
を呼び出した場合は "Content-Type: application/octet-stream\r\nContent-Transfer-Encoding: binary\r\n" というヘッダフィールドがその前に追加で付与されます。
RAW 形式で送信する場合。送信のために呼び出すことのできる関数は SendPostDataRaw()
のみです。1 回の呼び出しで送信されるデータは、そのまま Chunked データとしてまとめて送信されます。
すべての POST データを送信し終えたあとは必ず、NotifyFinishSendPostData()
を呼び出して、POST データの送信完了を通知してください。呼び出したあとは、処理が HTTP レスポンスの受信へと移行します。
6.3.5. 接続の開始
初期化で指定した URL に対して HTTP 接続を開始します。接続のために呼び出す関数には、接続が開始されるまで処理をブロックする Connect()
と、すぐに処理を返す ConnectAsync()
の 2 種類があります。また、接続をキャンセル状態にする Cancel()
も用意されています。
class nn::http::Connection { nn::Result Connect(void); nn::Result ConnectAsync(void); nn::Result Cancel(void); }
Connect()
はシステム全体で同時に接続可能な数の HTTP 接続がすでに行われていた場合に処理をブロックしますが、ConnectAsync()
はすぐにエラーとして処理を返します。
Cancel()
を呼び出すと HTTP 接続はキャンセル状態となり、以降その接続クラスでは通信が行えなくなります。
nn::http::Connection::Connect()
もしくは nn::http::Connection::ConnectAsync()
を使用して接続を開始した際、ヘッダ受信中にアクセスポイントの WAN 側のケーブルを抜いた場合無期限に受信を待ち続けてしまいます。
これを防ぐには、一定時間経過後に通信を切断(nn::http::Connection::Cancel()
)する処理を実装する必要があります。
6.3.6. レスポンスの受信
Connect()
などで接続が完了したあと、HTTP 通信の結果(レスポンス)を受信するには、メッセージボディならば Read()
を、レスポンスステータスならば GetStatusCode()
を、メッセージヘッダならば GetHeaderField()
または GetHeaderAll()
を呼び出します。引数 timeout
を持つオーバーロードは指定された時間で処理をタイムアウトさせることができます。タイムアウトした場合、内部で Cancel()
が呼び出され、接続はキャンセル状態になります。
class nn::http::Connection { nn::Result Read(u8* pBodyBuf, size_t bufLen); nn::Result Read(u8* pBodyBuf, size_t bufLen, const nn::fnd::TimeSpan& timeout); nn::Result GetStatusCode(s32* pStatusCodeCourier) const; nn::Result GetStatusCode(s32* pStatusCodeCourier, const nn::fnd::TimeSpan& timeout) const; nn::Result GetHeaderField( const char* pLabel, char* pFieldBuf, size_t bufSize, size_t* pFieldLengthCourier = NULL) const; nn::Result GetHeaderField( const char* pLabel, char* pFieldBuf, size_t bufSize, const nn::fnd::TimeSpan& timeout, size_t* pFieldLengthCourier = NULL) const; nn::Result GetHeaderAll( char* pHeaderBuf, size_t bufSize, size_t* pLengthCourier = NULL) const; nn::Result GetHeaderAll( char* pHeaderBuf, size_t bufSize, const nn::fnd::TimeSpan& timeout, size_t* pLengthCourier = NULL) const; }
Read()
は、pBodyBuf
に指定された bufLen
バイトのバッファにメッセージボディのデータを格納します。指定されたバッファサイズよりもメッセージボディのサイズが大きい場合は、バッファにできる限りのデータを格納して、バッファ不足を表す返り値(nn::http::ResultBodyBufShortage
)を返しますが、再度 Read()
を呼び出すことで続くデータの読み取りを継続することができます。それ以外でエラーが返された場合は、レスポンスの受信自体に失敗しています。ただし認証失敗などの HTTP ステータスエラーの場合は、エラーメッセージを示すメッセージボディの受信に成功しているため、通信成功時と同様の動作になります(つまりバッファ不足のときは nn::http::ResultBodyBufShortage
が、受信完了ならば IsSuccess()
が true
を返すインスタンスが返ります)。
GetStatusCode()
は、引数 pStatusCodeCourier
に指定された s32
型の変数にレスポンスステータスを格納します。通信エラーが発生したかどうかは、この関数で取得するレスポンスステータスで確認することができます。メッセージヘッダの受信が完了していない状態でこの関数の呼び出したときは、ヘッダ部の受信が完了するまで処理がブロックされます。先に Read()
を呼び出していた場合はヘッダ部の受信は完了していますので、この関数は処理をすぐに返します。
GetHeaderField()
は、引数 pFieldBuf
に指定された bufSize
バイトのバッファに pLabel
で指定されたラベルのフィールドデータを格納します。pFieldBuf
に NULL
、bufSize
に 0、pFieldLengthCourier
に NULL
以外を指定した場合は、指定されたラベルのフィールドデータのバイトサイズを pFieldLengthCourier
に格納します。
GetHeaderAll()
はすべてのメッセージヘッダを引数 pHeaderBuf
に指定された bufSize
バイトのバッファに格納します。pHeaderBuf
に NULL
、bufSize
に 0、pLengthCourier
に NULL
以外を指定した場合は、pLengthCourier
にメッセージヘッダの取得に必要なバッファサイズをバイト単位で格納します。メッセージヘッダの受信が完了していない状態でこれらの関数の呼び出したときは、ヘッダ部の受信が完了するまで処理がブロックされます。先に Read()
を呼び出していた場合はヘッダ部の受信は完了していますので、これらの関数は処理をすぐに返します。
6.3.7. 接続状況などの取得
HTTP 接続クラス自身のステータスや発生したエラーのエラーコード、レスポンス受信の進捗を取得するための関数が用意されています。
class nn::http::Connection { nn::Result GetStatus(nn::http::Status* pStatusBuf) const; nn::Result GetError(nn::http::ResultCode* pResultCodeBuf) const; nn::Result GetProgress(size_t* pReceivedLen, size_t* pContentLen) const; }
GetStatus()
は、引数 pStatusBuf
に指定されたバッファに接続状況を格納します。格納される接続状況は nn::http::Status
列挙子の値です。
GetError()
は、引数 pResultCodeBuf
に指定されたバッファにエラーコードを格納します。格納されるエラーコードは nn::http::ResultCode
列挙子の値です。
GetProgress()
は、引数 pReceivedLen
と pContentLen
に指定された変数に受信済みメッセージボディのバイトサイズと予定されるメッセージボディの総サイズを格納します。総サイズは HTTP レスポンスのメッセージヘッダ "Content-Length" の値ですので、メッセージヘッダに "Content-Length" が存在しなかった場合、pContentLen
には 0 が格納されます。
6.3.8. 接続の終了
レスポンスの受信がすべて完了し、インスタンスが不要になったときは必ず Finalize()
を呼び出してから破棄してください。接続先 URL を指定していない(Initialize()
を呼び出していない)インスタンスに対して呼び出す必要はありません。
class nn::http::Connection { nn::Result Finalize(void); }